PHP转义与编码函数小结
前面用到php转义、编码函数时,一直都很不知所以然,人云亦云,这篇文章用来总结下php转义函数的用法。
1、url_encode、url_decode
首先要说明这种encode的作用,url_encode会将字符串中除了
这里说明下我对post、get两种http请求方式关于urlencode的理解。
form表单以get形式提交数据时,是将请求追加到url后面。若将参数带到url中,需要手动进行urlencode,服务器接受方也要对应进行urldecode。
form表单以post形式提交数据,是把数据封装在http body中,这时便会有两种不同的形式。
①entype:application/x-www-form-urlencode:会对提交的数据自动进行urlencode,服务端接收到请求后会根据编码类型自动进行urldecode。
②entype:mutipare/form-data:二进制方式提交数据,不做urlencode,服务端自然也不会进行urldecode。
综上所述,当web中表单以post形式提交请求时,客户端并不需要手动进行urlencode,服务端接收数据后会自动根据请求类型来判断是否进行urldecode,也无需手动。
curl是大家都很喜欢用的一个请求模拟工具,那么问题又来了,curl中post方式又是否需要手动进行urlencode?(get方式显而易见是需要的)
实际上,curl来post数据时也有两种方式,一种是将所有参数拼做一串字符串,这相当于上述①,不同的是curl并不会自动urlencode,所有这里客户端需要手动,但服务端是会自动进行urldecode的;另一种则将参数按一个数组的方式提交,这相当于上述②,并不需要进行urlencode与urldecode。
=============================2017-10-15=============================
最近无意中发现,nginx会对urlencode做一些意外的处理,当客户端以post方式,Content-Type: application/x-www-form-urlencoded提交时,nginx服务器会自动进入一次urldecode,这个过程应用层是无感的;而单客户端以get方式提交时,如果客户端手动加上了urlencode,此时nginx会“自作聪明”,对数据自动进行一次urldecode,fastcgi拿到的数据就是urldecode后的内容了,跟我们所想的内容并不一样。
2、json_encode、json_decode
可以接受除了resource 类型之外的任何数据类型 ,前提是只能支持UTF8格式的编码。
3、base64_encode、base64_encode
base64_encode的作用是对给定的字符串使用base64编码,设计此种编码是为了使二进制数据可以通过非纯 8-bit 的传输层传输,例如电子邮件的主体就需要用到该函数来编码。据说Base64-encoded后的数据要比原始数据多占用 33% 左右的空间。
4、magic_quotes_gpc
magic_quotes_gpc设置是否自动为GPC(GET,POST,COOKIE)传来的数据中的某些字符进行转义, 可以使用get_magic_quotes_gpc()检测其设置。这些字段包括单引号(’)、双引号(”)、反斜线(\)与 NULL(NULL 字符)等字符。注意,若开启为on,输入会自动转义,但输出不会自动进行反转义(即会按转义后字符串输出)。
若php中该项设置为off,则代码必须对输入进行字符串转义,以保证sql安全,常用函数addslashes。php6已取消该项,所以代码不应该 过分依赖系统默认设置。
5、addslashes()、stripslashes()
这个函数就是为magic_quotes_gpc为off时而用,手动为字符串转义,预定义字符包括:
单引号 (‘)、双引号 (“)、反斜杠 (\)、NULL。
strupslaches()负责将转义字符反转义。
6、mysql_escape_string()、mysql_escape_real_string()
首先:不要使用mysql_escape_string,它已被弃用,请使用mysql_real_escape_string代替它。
mysql_escape_real_string()与addslashes()有什么区别呢?两者都是为输入数据做安全转义,不同的有两点。第一,mysql_escape_real_string()转义的字符集比addslashes多(包括了\x00,\n,\r,\,’,”,\x1a),第二,前者的转义是基于mysql指定编码后的字符,后者是基于当前环境的编码字符。怎么理解第二点,看下面的栗子:
首先创建一个gbk表格。
1 2 3 4 5 | CREATE TABLE users( username VARCHAR(32) CHARACTER SET GBK, password VARCHAR(32) CHARACTER SET GBK, PRIMARY KEY(username) ); |
然后,注入username=chr(0xbf) . chr(0×27) . ‘ OR username = username ‘
1 2 3 4 5 6 7 8 9 | $mysql = array(); $db = mysqli_init(); $db->real_connect('localhost', 'lorui', 'lorui.com', 'lorui_db'); $_POST['username'] = chr(0xbf) . chr(0×27) . ' OR username = username '; $_POST['password'] = 'guess'; $mysql['username'] = addslashes($_POST['username']); $mysql['password'] = addslashes($_POST['password']); $sql = “SELECT * FROM users WHERE username = '{$mysql['username']}' AND password = '{$mysql['password']}'”; $result = $db->query($sql); if ($result->num_rows) { /* 成功 */ } else { /* 失败 */ } |
0xbf27经过addslashes转义后会变成0xbf5c27,这对于mysql的编码来说恰好是注入了一个单引号。原因详见文章:http://www.jb51.net/article/49205.htm
最后介绍下这个函数的原型:mysql_real_escape_string(string,connection)
第一个参数不用解释,第二个参数是指指定的mysql链接,这使转义跟选定的编码很有关系(记不记得建立mysql链接的时候要选择编码?),若为空则指定上一个可用链接。
7、addcslashes()和stripcslashes()
addcslashes()以C 语言风格使用反斜线转义字符串中的字符,这个函数很少人去用,但是应该注意的是:当选择对字符 0,a,b,f,n,r,t 和 v 进行转义时,它们将被转换成 \0,\a,\b,\f,\n,\r,\t 和 \v。在 PHP 中,只有 \0(NULL),\r(回车符),\n(换行符)和 \t(制表符)是预定义的转义序列, 而在 C 语言中,上述的所有转换后的字符都是预定义的转义序列。同理stripcslashes()的功能就是去除其转义。
8、htmlentities() 和html_entity_decode()
htmlentities() 的作用是让浏览器输出html代码,不去解析该html代码了,比如说在发帖的时候,为了不让其输入的html代码生效,可以使用htmlentities。
函数原型:htmlentities(string,quotestyle,character-set)
string是必选参数,是需要转换的字符串。其余可选,quotestyle规定如何编码单引号和双引号:ENT_COMPAT – 默认。仅编码双引号;ENT_QUOTES – 编码双引号和单引号;ENT_NOQUOTES – 不编码任何引号。character-set是规定转换用的字符集,常用的有UTF-8/GB-2312/ISO-8859-1(默认)。
html_entity_decode()函数的作用相反,把html实体转换回html标签。
9、htmlspecialchars()和htmlspecialchars_decode()
htmlspecialchars()这个函数的功能与htmlentities()是相似的,不同的是作用的结果集较小,只针对& ‘ ” < 和 > 这几个特殊符号。
http_build_query与query_str Linux文件权限详解