[总结+讨论]php 字符串过滤 各类函数应用

phnessu4 2009-02-01 12:49:17
首先自我检讨一下..因为正则不过关,所以自己写的过滤条件基本失败了...
上网查的函数也看不懂,改了也出错....

在csdn的各路神仙指点下,略微开了点窍...原问题帖链接

现放出各个路子的函数,供各位已经死过还尚未死成的同志使用....
希望大家积极补充,把平时常用的方法帖出来

基础函数
-----------------------------------------------------------------------------------
其实mysql和php自带很多函数可以处理字符问题,下面给出几个会经常用到的.
ps:由于php6开始不支持magic_quotes_gpc,所以下面的东西都是假设在magic_quotes_gpc=off的条件上(不知道php6会出什么新东西....)

mysql_real_escape_string()
定义:函数转义 SQL 语句中使用的字符串中的特殊字符。
语法: mysql_real_escape_string(string,connection)
说明:本函数将 string 中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于 mysql_query()。
由于实例代码过长,给出函数解释链接 w3school phpnet

addSlashes()
定义:addslashes() 函数在指定的预定义字符前添加反斜杠。
语法:addslashes(string)
注释:默认情况下,PHP 指令 magic_quotes_gpc 为 on,对所有的 GET、POST 和 COOKIE 数据自动运行 addslashes()。不要对已经被 magic_quotes_gpc 转义过的字符串使用 addslashes(),因为这样会导致双层转义。遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测。
由于实例代码过长,给出函数解释链接 w3school phpnet
相关函数
StripSlashes()去掉反斜线字符。(解释过滤字符时用)

mb_convert_encoding()
PHP的内码转换函数
版本(PHP 4 >= 4.0.6, PHP 5)
这个函数可以将各种编码互相转换
相关链接 phpnet

iconv()
php内码转换函数,同上
因为iconv()在转换gb2312时的bug,所以要这样处理
iconv( "UTF-8", "gb2312//IGNORE" , $str)

ignore的意思是忽略转换时的错误,发现iconv在转换字符"—"到gb2312时会出错,如果没有ignore参数,所有该字符后面的字符串都无法被保存。
另外mb_convert_encoding没有这个bug,所以最好的写法是:
mb_convert_encoding($str,"gb2312", "UTF-8");

但是需要先enable mbstring 扩展库。
也可以把mysql数据库的collation设成utf-8就不用作转换了
三句mysql真言

SET NAMES utf8;
SET CHARACTER SET utf8;
SET COLLATION_CONNECTION='utf8_general_ci';

相关链接 phpnet
资料参考 link1 link2 link3

自定函数1
-----------------------------------------------------------------------------------

网上找的转换函数,将GB2312进行转换的,修改为utf-8后转换错误,无法解析中文.....期待正则狂人...
<?php
function escape($str) {
preg_match_all("/[\x80-\xff].|[\x01-\x7f]+/",$str,$r);
$ar = $r[0];
foreach($ar as $k=>$v) {
if(ord($v[0]) < 128)
$ar[$k] = rawurlencode($v);
else
$ar[$k] = "%u".bin2hex(iconv("GB2312","UCS-2",$v));
}
return join("",$ar);
}

function unescape($str) {
$str = rawurldecode($str);
preg_match_all("/(?:%u.{4})|.+/",$str,$r);
$ar = $r[0];
foreach($ar as $k=>$v) {
if(substr($v,0,2) == "%u" && strlen($v) == 6)
$ar[$k] = iconv("UCS-2","GB2312",pack("H4",substr($v,-4)));
}
return join("",$ar);
}
?>


自定函数2
-----------------------------------------------------------------------------------

感谢论坛gingzai777 ,高手就是不一样,一眼就能看出问题所在.....
以后php过滤用这个行了,不需要顾虑文件编码了.....
<?php
function addslashes_str($str){
$str=addslashes($str);
$str=str_replace($str,";",'\;');
return $str;
}
function stripslashes_str($str){
$str=stripslashes($str);
$str=str_replace($str,'\;',";");
return $str;
}
?>


-------------------------------------------------------------------------------------
ps:如果有什么错误,希望大家指出,另外希望大家把平时用到的一些方法提供一下,互相学习...散分...


我写的原文
...全文
5071 35 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
yyszh 2012-08-14
  • 打赏
  • 举报
回复
好久不来csdn了,今天偶然看到这个好帖,顶一下。
pygmalion 2011-10-11
  • 打赏
  • 举报
回复
华山论剑啊!
都是高人!
混迹在Amoy 2010-12-04
  • 打赏
  • 举报
回复
好东西啊。。对于我们这些入门PHPer帮助太大了,不然总被误导,支持下
kaifadi 2010-09-04
  • 打赏
  • 举报
回复
总结的非常好,可惜没有什么人看!虽然过去一年了!
调皮的蟠桃 2010-06-04
  • 打赏
  • 举报
回复
总结的太好了,我要好好学习php。哈哈!!
t240034137 2010-05-11
  • 打赏
  • 举报
回复
。。。。今天为了过滤用户输入信息才看见这个帖子! 哎! 相见恨晚呀!
foolbirdflyfirst 2009-12-02
  • 打赏
  • 举报
回复
这帖子真不错,为啥我现在才看到。精华贴呀。
ytphp 2009-12-02
  • 打赏
  • 举报
回复
好东西啊!!
surfchen 2009-02-02
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 mikespook 的回复:]
这里调用的是 mysql lib 提供的 mysql_set_character_set 函数。关于这个更底层的 mysql lib,可以看这个:http://jabberd2.xiaoka.com/ticket/177,尤其是这个说明:http: //dev.mysql.com/doc/refman/5.0/en/mysql-set-character-set.html

This function works like the SET NAMES statement, but also sets the value of mysql->charset, and thus affects the character set used by mysql_real_escape_string()
[/Quote]
嗯,对的,mysql的那个核心结构里,有charset这个成员。mysql会根据这个charset来调用不同的charset的handler判断多字节,例如gbk就是strings/ctype-gbk.c下的ismbchar_gbk。而set names是不会去设置这个成员变量的。

我上面是说mysql的c源代码,大家可以忽略。
surfchen 2009-02-02
  • 打赏
  • 举报
回复
补充一句:大家不要认为addslashes和mysql有什么关系,addslashes只不过正好可以用在mysql这个场景下而已。当然如我上面所说,实际上addslashes和mysql所要求的过滤还是有一些区别的。
mikespook 2009-02-02
  • 打赏
  • 举报
回复
刚才看了一下 php 5.2.8 的 ext/mysql/php_mysql.c,1099 行:

PHP_FUNCTION(mysql_set_charset)
{
zval *mysql_link = NULL;
char *csname;
int id = -1, csname_len;
php_mysql_conn *mysql;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &csname, &csname_len, &mysql_link) == FAILURE) {
return;
}

if (ZEND_NUM_ARGS() == 1) {
id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
CHECK_LINK(id);
}

ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);

if (!mysql_set_character_set(&mysql->conn, csname)) {
RETURN_TRUE;
} else {
RETURN_FALSE;
}
}

这里调用的是 mysql lib 提供的 mysql_set_character_set 函数。关于这个更底层的 mysql lib,可以看这个:http://jabberd2.xiaoka.com/ticket/177,尤其是这个说明:http://dev.mysql.com/doc/refman/5.0/en/mysql-set-character-set.html

This function works like the SET NAMES statement, but also sets the value of mysql->charset, and thus affects the character set used by mysql_real_escape_string()
mikespook 2009-02-02
  • 打赏
  • 举报
回复
刚才看了一下 php 5.2.8 的 ext/mysql/php_mysql.c,1099 行:

PHP_FUNCTION(mysql_set_charset)
{
zval *mysql_link = NULL;
char *csname;
int id = -1, csname_len;
php_mysql_conn *mysql;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &csname, &csname_len, &mysql_link) == FAILURE) {
return;
}

if (ZEND_NUM_ARGS() == 1) {
id = php_mysql_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
CHECK_LINK(id);
}

ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, &mysql_link, id, "MySQL-Link", le_link, le_plink);

if (!mysql_set_character_set(&mysql->conn, csname)) {
RETURN_TRUE;
} else {
RETURN_FALSE;
}
}

这里调用的是 mysql lib 提供的 mysql_set_character_set 函数。关于这个更底层的 mysql lib,可以看这个:http://jabberd2.xiaoka.com/ticket/177,尤其是这个说明:http://dev.mysql.com/doc/refman/5.0/en/mysql-set-character-set.html

This function works like the SET NAMES statement, but also sets the value of mysql->charset, and thus affects the character set used by mysql_real_escape_string()
phnessu4 2009-02-02
  • 打赏
  • 举报
回复
果然还是要好好看手册.....
刚才又加了100,散....
surfchen 2009-02-02
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 phnessu4 的回复:]
4.疑问....
如果说php6取消了magic_quotes_gpc,而addslashes()根据surfchen说的不安全,那过滤函字符用什么?
php6有什么新花样?
还是mysqli_real_escape_string() ????
[/Quote]
为什么取消magic_quotes_gpc呢,我来说明一下吧。

首先,当magic_quotes_gpc存在的时候,我们程序员是否因此而获益呢?答案是否定的。正因为存在magic_q这个东西,导致我们在写代码的时候,不得不判断这个magic_q是否开启,然后采取不同的动作。也就是,magic_q如果存在,程序里必须处理“它开启”和“它不开启”这两种情况。而如果没有magic_q,程序只需要处理“它不开启”这一种情况了。

其次,addslashes不应该作为一种统一的过滤字符函数。因为,在不同的应用里,存在不同的过滤规则。例如,在MySQL里,按照标准,是需要过滤\x00, \n, \r, \, ', "和\x1a。这里处理\n\r,是为了MySQL的log存储。而在不同编码环境下,MySQL的过滤处理又略有不同。所以说addslashes是不可以用来对进入MySQL的数据进行过滤的。 我再举个例子,html的过滤,至少要过滤<和>吧,这个就很明显不能用addslashes来处理了。关于这个问题的更深入的例子,如果有兴趣,可以阅读我这篇文章:utf8_decode的安全性。如果比较复杂,如果时间不多,就不要看了。

那么mysql的数据应该用什么来过滤呢?对应如下:
mysql: mysql_real_escape_string
mysqli:mysqli_real_escape_string
pdo:quote

实际上,一个好的数据库类库,已经不需要程序员直接调用过滤程序了。看下面的例子:
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < ? AND colour = ?');
$sth->execute(array(150, 'red'));


这个例子,是PDO的例子。PDO引入了一个叫占位变量的概念,也就是上面的问号。上面的execute()的作用,就是把prepare里的问号,替换为150和red,并执行。在替换过程里,它自动做了quote(),也就是过滤字符。下面是我实现的一个类库的一个例子,也是引入了类似的概念。实际上,大多数优秀的数据类库都有占位变量和prepareStatement的概念的。
$sjk->initSql('select * from wp_users where user_login=#1 limit 1');
$sjk->setString(1,$name);
$rs=$sjk->query();



另外,关于php6么,当然是不会引入如同magic_quotes_gpc这样的东西了。magic_q是一个畸形的产物,源自于PHP核心开发团队的不严谨。
surfchen 2009-02-02
  • 打赏
  • 举报
回复
不是php自身实现的。

php的数据库实现,底层是使用一个叫libmysql的c库。其实无论是PHP,还是python,还是pecl,还是C,操作mysql几乎都是通过libmysql来实现的(当然有其他的实现,在此不表)。

而libmysql里,有一个叫mysql_set_charset的函数,这个函数被PHP封装起来,成为了PHP的函数。mikespook在上面已经提到了这一点。
fxs_2008 2009-02-02
  • 打赏
  • 举报
回复
看了一下,


mysql_set_charset

(PHP 5 >= 5.2.3)

mysql_set_charset — Sets the client character set

是新函数

手册里不详细,这个实质是是PHP自身的函数,而不是mysql机制

mysql的机制在不得不用的情况下,仍要用set names

说下简单的例子,如果你用不是php,要连mysql数据库呢?



phnessu4 2009-02-02
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 yctin 的回复:]
这样的帖应该要顶一下...加一下精

但我们的版主好像半退休状态了
[/Quote]

呵呵,以后这样的帖子会有很多的,大家不嫌烦就行.......
小白飘过~~~
yctin 2009-02-02
  • 打赏
  • 举报
回复
这样的帖应该要顶一下...加一下精

但我们的版主好像半退休状态了
程序猿之殇 2009-02-02
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 phnessu4 的回复:]
引用 20 楼 jakey9826 的回复:
很少看到这么治学严谨的兄弟了.
汗颜!


感觉这样子,学习的氛围才会好,要不然小白是挖不出内核的...
[/Quote]
希望php版块如此吧,呵呵.
phnessu4 2009-02-02
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 jakey9826 的回复:]
很少看到这么治学严谨的兄弟了.
汗颜!
[/Quote]

感觉这样子,学习的氛围才会好,要不然小白是挖不出内核的...
加载更多回复(14)

21,893

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧