PHP函数 mysql_real_escape_string 与 addslashes 的区别
2016-07-17 09:18
806 查看
addslashes 和 mysql_real_escape_string 都是为了使数据安全的插入到数据库中而进行的过滤,那么这两个函数到底是有什么区别呢?
首先,我们还是从PHP手册入手:
手册上addslashes转义的字符是单引号(')、双引号(")、反斜线(\)与NUL(NULL 字符)。
mysql_real_escape_string转义的字符并没有被提到,只是说了一句:
注意:mysql_real_escape_string() 并不转义% 和_。
为什么PHP手册没有说呢?因为其实这是个MySql的C的API,所以我们需要查下MySql手册,上面是这么说的:
编码的字符为NUL (ASCII 0)、'\n'、'\r'、'\'、'''、'"'、以及Control-Z(请参见9.1节,“文字值”)。(严格地讲,MySQL仅需要反斜杠和引号字符,用于引用转义查询中的字符串。该函数能引用其他字符,从而使得它们在日志文件中具有更好的可读性)。
MySql手册上面的话总是令人费解的。
我们为了更深层次的探究这两个函数的不同,还是去看一看PHP的源码吧。
这是PHP的addslashes函数:
很显然,它调用了 php_addslashes,我们继续看这个函数,
结果又是在调用 php_addslashes_ex,我们就像在剥洋葱一样,一步一步的接近真理。
上面的函数已经非常清楚的描述出都要转义哪些字符了,现在我们去看一看 mysql_real_escape_string
这个不在string.c里了,是在mysql扩展中。
这个函数并没有像上面的那样剥洋葱,而是直接调用了MySql的C的API,mysql_real_escape_string()。
需要注意的是,这个函数在调用 mysql_real_escape_string 这个API之前,先是判断了是否连接上了数据库,
所以,这就意味着 mysql_real_escape_string 必须是连接数据库之后才能使用。为了证实这一点,我们来简单的实验下:
结果:
果然报错了,显示没有链接上数据库。
好了,总结就先告一段落。
终于明白为什么那么多开源的程序比如 Discuz 用 addslashes 而不用 mysql_real_escape_string 了。
所以呢,以后也就用 addslashes 好了,暂时可以忘记掉 mysql_real_escape_string 了!
首先,我们还是从PHP手册入手:
手册上addslashes转义的字符是单引号(')、双引号(")、反斜线(\)与NUL(NULL 字符)。
mysql_real_escape_string转义的字符并没有被提到,只是说了一句:
注意:mysql_real_escape_string() 并不转义% 和_。
为什么PHP手册没有说呢?因为其实这是个MySql的C的API,所以我们需要查下MySql手册,上面是这么说的:
编码的字符为NUL (ASCII 0)、'\n'、'\r'、'\'、'''、'"'、以及Control-Z(请参见9.1节,“文字值”)。(严格地讲,MySQL仅需要反斜杠和引号字符,用于引用转义查询中的字符串。该函数能引用其他字符,从而使得它们在日志文件中具有更好的可读性)。
MySql手册上面的话总是令人费解的。
我们为了更深层次的探究这两个函数的不同,还是去看一看PHP的源码吧。
这是PHP的addslashes函数:
PHP_FUNCTION(addslashes) { zval **str; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(str); if (Z_STRLEN_PP(str) == 0) { RETURN_EMPTY_STRING(); } RETURN_STRING(php_addslashes(Z_STRVAL_PP(str), Z_STRLEN_PP(str), &Z_STRLEN_P(return_value), 0 TSRMLS_CC), 0); }
很显然,它调用了 php_addslashes,我们继续看这个函数,
PHPAPI char *php_addslashes(char *str, int length, int *new_length, int should_free TSRMLS_DC) { return php_addslashes_ex(str, length, new_length, should_free, 0 TSRMLS_CC); }
结果又是在调用 php_addslashes_ex,我们就像在剥洋葱一样,一步一步的接近真理。
PHPAPI char *php_addslashes_ex(char *str, int length, int *new_length, int should_free, int ignore_sybase TSRMLS_DC) { /* maximum string length, worst case situation */ char *new_str; char *source, *target; char *end; int local_new_length; if (!new_length) { new_length = &local_new_length; } if (!str) { *new_length = 0; return str; } new_str = (char *) safe_emalloc(2, (length ? length : (length = strlen(str))), 1); source = str; end = source + length; target = new_str; if (!ignore_sybase && PG(magic_quotes_sybase)) { while (source < end) { switch (*source) { case '\0': *target++ = '\\'; *target++ = '0'; break; case '\'': *target++ = '\''; *target++ = '\''; break; default: *target++ = *source; break; } source++; } } else { while (source < end) { switch (*source) { case '\0': *target++ = '\\'; *target++ = '0'; break; case '\'': case '\"': case '\\': *target++ = '\\'; /* break is missing *intentionally* */ default: *target++ = *source; break; } source++; } } *target = 0; *new_length = target - new_str; if (should_free) { STR_FREE(str); } new_str = (char *) erealloc(new_str, *new_length + 1); return new_str; }
上面的函数已经非常清楚的描述出都要转义哪些字符了,现在我们去看一看 mysql_real_escape_string
这个不在string.c里了,是在mysql扩展中。
PHP_FUNCTION(mysql_real_escape_string) { zval *mysql_link = NULL; char *str; char *new_str; int id = -1, str_len, new_str_len; php_mysql_conn *mysql; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r", &str, &str_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); new_str = safe_emalloc(str_len, 2, 1); new_str_len = mysql_real_escape_string(&mysql->conn, new_str, str, str_len); new_str = erealloc(new_str, new_str_len + 1); RETURN_STRINGL(new_str, new_str_len, 0); }
这个函数并没有像上面的那样剥洋葱,而是直接调用了MySql的C的API,mysql_real_escape_string()。
需要注意的是,这个函数在调用 mysql_real_escape_string 这个API之前,先是判断了是否连接上了数据库,
CHECK_LINK(id); // 就是这句
所以,这就意味着 mysql_real_escape_string 必须是连接数据库之后才能使用。为了证实这一点,我们来简单的实验下:
<?php echo mysql_real_escape_string("fdsafda'fdsa");
结果:
Warning: mysql_real_escape_string() [function.mysql-real-escape-string]: Access denied for user 'ODBC'@'localhost' (using password: NO) in PHPDocument1 on line 2 Warning: mysql_real_escape_string() [function.mysql-real-escape-string]: A link to the server could not be established in PHPDocument1 on line 2
果然报错了,显示没有链接上数据库。
好了,总结就先告一段落。
终于明白为什么那么多开源的程序比如 Discuz 用 addslashes 而不用 mysql_real_escape_string 了。
所以呢,以后也就用 addslashes 好了,暂时可以忘记掉 mysql_real_escape_string 了!
相关文章推荐
- 专访阿里巴巴研究员“赵海平”:Facebook的PHP底层性能优化之路(HipHop,HHVM)
- 【总结2】PhpStorm利用XDebug调试PHP技巧
- 【总结1】PhpStorm配置XDebug(远程)调试PHP
- 【译】PHP之道(PHP the right way)
- 【安居客】资深PHP软件开发工程师
- PHP不使用?>结尾会更好!
- PHP读写大“二进制”文件,不必申请很大内存(fopen、fread、fwrite、fclose)
- PHP中file_exists与is_file、is_dir的区别,以及执行效率的比较
- PHP安全相关的配置
- Github.com上有哪些比较有趣的PHP项目?
- PHP同时上传“多个”文件示例,并格式化$_FILES数组信息
- PHP的继承方法如何获取子类名?get_class() 和 get_called_class()
- PHP中curl的CURLOPT_POSTFIELDS参数使用细节
- PHP如何自动识别第三方Restful API的内容,自动渲染成 json、xml、html、serialize、csv、php等数据
- PHP下载/采集远程图片到本地
- 【问底】徐汉彬:PHP7和HHVM的性能之争
- Github上的PHP资源汇总大全
- PHP 正则表达式匹配函数 preg_match 与 preg_match_all
- PHP合并2个数字键数组的值
- 编译安装 Zend Opcache 缓存Opcache,加速 PHP