PHP函数 mysql_real_escape_string 与 addslashes 的区别

时间:2022-09-08 00:00:47

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 了!

PHP函数 mysql_real_escape_string 与 addslashes 的区别的更多相关文章

  1. magic&lowbar;quotes&lowbar;gpc、mysql&lowbar;real&lowbar;escape&lowbar;string、addslashes的区别及用法

    本篇文章,主要先重点说明magic_quotes_gpc.mysql_real_escape_string.addslashes 三个函数方法的含义.用法,并举例说明.然后阐述下三者间的区别.关系.一 ...

  2. DLL导出函数和类的定义区别 &lowbar;&lowbar;declspec&lpar;dllexport&rpar;

    DLL导出函数和类的定义区别 __declspec(dllexport) 是有区别的, 请看 : //定义头文件的使用方,是导出还是导入 #if defined(_DLL_API) #ifndef D ...

  3. SQL Server排序函数row&lowbar;number和rank的区别

    SQL Server排序函数row_number和rank的区别 直接看测试结果 declare @table table(name varchar(100),amount int, memo var ...

  4. 详解 &dollar;&lowbar;SERVER 函数中QUERY&lowbar;STRING和REQUEST&lowbar;URI区别

    详解 $_SERVER 函数中QUERY_STRING和REQUEST_URI区别 http://blog.sina.com.cn/s/blog_686999de0100jgda.html   实例: ...

  5. onAttachedToWindow &lpar;&rpar; 和 onDetachedFromWindow &lpar;&rpar; &semi; 以及更新视图的函数ondraw&lpar;&rpar; 和dispatchdraw&lpar;&rpar;的区别

    protected void onAttachedToWindow() This is called when the view is attached to a window. At this po ...

  6. oracle函数和存储过程有什么区别

    oracle函数和存储过程有什么区别 1. 返回值的区别,函数有1个返回值,而存储过程是通过参数返回的,可以有多个或者没有 2.调用的区别,函数可以在查询语句中直接调用,而存储过程必须单独调用. 函数 ...

  7. 函数strlen&lpar;&rpar;和sizeof的区别

    函数strlen()和sizeof的区别: #include<stdio.h> #include<stdlib.h> #include<string.h> #def ...

  8. Linux可重入函数和线程安全的区别与联系&lpar;转&rpar;

    *****可重入函数 函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入. 当程序运行到某一个函数的时候,可能因为硬件中断或者异常而使得在用户正在执行的代码暂时终端转而 ...

  9. Python&colon; dict setdault函数与collections&period;defaultdict&lpar;&rpar;的区别

    setdault用法 >>>dd={'hy':1,'hx':2} >>>cc=dd.setdefault('hz',1) >>>cc      返 ...

随机推荐

  1. 变量声明---let&comma;const&comma;解构

    let在很多方面与var是相似的,但是可以帮助大家避免在JavaScript里常见一些问题. const是对let的一个增强,它能阻止对一个变量再次赋值. 块作用域 当用let声明一个变量,它使用的是 ...

  2. SpringMVC &commat;ModelAttribute注解

    /**     * 1. 有 @ModelAttribute 标记的方法, 会在每个目标方法执行之前被 SpringMVC 调用!      * 2. @ModelAttribute 注解也可以来修饰 ...

  3. JS简介

    JS是一本广泛应用于浏览器客户端的脚本语言,由netspace公司设计,当时和sun公司合作,所以名字取得像java JS的常见用途:1)HTML DOM操作(节点操作,比如添加.修改.删除节点 ) ...

  4. speex介绍

    1介绍 Speex是一套主要针对语音的开源免费,无专利保护的音频压缩格式.Speex工程着力于通过提供一个可以替代高性能语音编解码来降低语音应用输入门槛 .另外,相对于其它编解码器,Speex也很适合 ...

  5. css3 简单动画

    <script> <!-- var x,y,n=0,ny=0,rotINT,rotYINT function rotateDIV() { x=document.getElementB ...

  6. &lbrack;Javascript&rsqb; How to use JavaScript&&num;39&semi;s String&period;replace

    In JavaScript, you can change the content of a string using the replace method. This method signatur ...

  7. Selenium 上传文件失败,解决办法一

    昨个改程序遇到一个问题,UI上面有需要上传文件的地方.但是我不知道怎么让Selenium完成 点击上传文件按钮->在弹出的文件选择窗口中选择路径和文件,点确定. 要知道弹出窗口属于window的 ...

  8. QtQuick 中的 qml 与 Qt 的 C&plus;&plus;

    QtQuick 可以使用内置的 JavaScript 引擎加载相应的 JS 代码,使用起来特别方便. 在 Qt 中使用 C++ 开发底层,QtQuick 用来加载.处理图像,然后使用 Qt 提供的接口 ...

  9. DataGrid获取单元格的值

    string str = (dataGrid.Columns[0].GetCellContent(dataGrid.Items[0]) as TextBlock).Text;

  10. 【转载】Ocelot网关的路由热更新

    调用API修改Ocelot的配置文件 May 11, 2018 | netcoreocelot | 410 阅读 Ocelot是一个基于.net core的开源webapi服务网关开源项目,功能比较强 ...