先看手册说明
1.addslashes
说明 ¶
$str
)
返回字符串,该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线。这些字符是单引号(')、双引号(")、反斜线(\)与 NUL(NULL
字符)。
一个使用 addslashes() 的例子是当你要往数据库中输入数据时。 例如,将名字 O'reilly 插入到数据库中,这就需要对其进行转义。 强烈建议使用 DBMS 指定的转义函数 (比如 MySQL 是 mysqli_real_escape_string(),PostgreSQL 是 pg_escape_string()),但是如果你使用的 DBMS 没有一个转义函数,并且使用 \ 来转义特殊字符,你可以使用这个函数。 仅仅是为了获取插入数据库的数据,额外的 \ 并不会插入。 当 PHP 指令magic_quotes_sybase 被设置成 on 时,意味着插入 ' 时将使用 ' 进行转义。
PHP 5.4 之前 PHP 指令 magic_quotes_gpc 默认是 on, 实际上所有的 GET、POST 和 COOKIE 数据都用被 addslashes() 了。 不要对已经被magic_quotes_gpc 转义过的字符串使用 addslashes(),因为这样会导致双层转义。 遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测。
mysql_real_escape_string
(PHP 4 >= 4.3.0, PHP 5)
mysql_real_escape_string — 转义 SQL 语句中使用的字符串中的特殊字符,并考虑到连接的当前字符集
说明 ¶
$unescaped_string
[,
resource $link_identifier
] )
本函数将 unescaped_string
中的特殊字符转义,并计及连接的当前字符集,因此可以安全用于 mysql_query()。
/* {{{ php_addslashes
*/
PHPAPI char *php_addslashes(char *str, int length, int *new_length, int should_free 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;
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;
}
/* }}} */
MYSQLND_METHOD(mysqlnd_conn_data, escape_string)(MYSQLND_CONN_DATA * const conn, char * newstr, const char * escapestr, size_t escapestr_len TSRMLS_DC)
{
size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, escape_string);
ulong ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::escape_string");
DBG_INF_FMT("conn=%llu", conn->thread_id);
if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
DBG_INF_FMT("server_status=%u", conn->upsert_status->server_status);
if (conn->upsert_status->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) {
ret = mysqlnd_cset_escape_quotes(conn->charset, newstr, escapestr, escapestr_len TSRMLS_CC);
} else {
ret = mysqlnd_cset_escape_slashes(conn->charset, newstr, escapestr, escapestr_len TSRMLS_CC);
}
conn->m->local_tx_end(conn, this_func, PASS TSRMLS_CC);
}
DBG_RETURN(ret);
}
/* {{{ mysqlnd_cset_escape_quotes */
PHPAPI ulong mysqlnd_cset_escape_quotes(const MYSQLND_CHARSET * const cset, char *newstr,
const char * escapestr, size_t escapestr_len TSRMLS_DC)
{
const char *newstr_s = newstr;
const char *newstr_e = newstr + 2 * escapestr_len;
const char *end = escapestr + escapestr_len;
zend_bool escape_overflow = FALSE;
DBG_ENTER("mysqlnd_cset_escape_quotes");
for (;escapestr < end; escapestr++) {
unsigned int len = 0;
/* check unicode characters */
if (cset->char_maxlen > 1 && (len = cset->mb_valid(escapestr, end))) {
/* check possible overflow */
if ((newstr + len) > newstr_e) {
escape_overflow = TRUE;
break;
}
/* copy mb char without escaping it */
while (len--) {
*newstr++ = *escapestr++;
}
escapestr--;
continue;
}
if (*escapestr == '\'') {
if (newstr + 2 > newstr_e) {
escape_overflow = TRUE;
break;
}
*newstr++ = '\'';
*newstr++ = '\'';
} else {
if (newstr + 1 > newstr_e) {
escape_overflow = TRUE;
break;
}
*newstr++ = *escapestr;
}
}
*newstr = '\0';
if (escape_overflow) {
DBG_RETURN((ulong)~0);
}
DBG_RETURN((ulong)(newstr - newstr_s));
}
/* }}} */
/* {{{ mysqlnd_cset_escape_slashes */
PHPAPI ulong mysqlnd_cset_escape_slashes(const MYSQLND_CHARSET * const cset, char *newstr,
const char * escapestr, size_t escapestr_len TSRMLS_DC)
{
const char *newstr_s = newstr;
const char *newstr_e = newstr + 2 * escapestr_len;
const char *end = escapestr + escapestr_len;
zend_bool escape_overflow = FALSE;
DBG_ENTER("mysqlnd_cset_escape_slashes");
DBG_INF_FMT("charset=%s", cset->name);
for (;escapestr < end; escapestr++) {
char esc = '\0';
unsigned int len = 0;
/* check unicode characters */
if (cset->char_maxlen > 1 && (len = cset->mb_valid(escapestr, end))) {
/* check possible overflow */
if ((newstr + len) > newstr_e) {
escape_overflow = TRUE;
break;
}
/* copy mb char without escaping it */
while (len--) {
*newstr++ = *escapestr++;
}
escapestr--;
continue;
}
if (cset->char_maxlen > 1 && cset->mb_charlen(*escapestr) > 1) {
esc = *escapestr;
} else {
switch (*escapestr) {
case 0:
esc = '0';
break;
case '\n':
esc = 'n';
break;
case '\r':
esc = 'r';
break;
case '\\':
case '\'':
case '"':
esc = *escapestr;
break;
case '\032':
esc = 'Z';
break;
}
}
if (esc) {
if (newstr + 2 > newstr_e) {
escape_overflow = TRUE;
break;
}
/* copy escaped character */
*newstr++ = '\\';
*newstr++ = esc;
} else {
if (newstr + 1 > newstr_e) {
escape_overflow = TRUE;
break;
}
/* copy non escaped character */
*newstr++ = *escapestr;
}
}
*newstr = '\0';
if (escape_overflow) {
DBG_RETURN((ulong)~0);
}
DBG_RETURN((ulong)(newstr - newstr_s));
}
/* }}} */
NO_BACKSLASH_ESCAPES:反斜杠“\”作为普通字符而非转义符.
4.总结
addslashes 和 mysql_real_escape_string如何选择哪个?
sql注入是数据库的行为。所以最好的做法是在入库的时候进行处理。所以提倡在入库的时候,用php提供的数据库的相关的转义函数。
mysql 就用 mysql_real_escape_string,pdo 的就用 quote 。
所以不太提倡一上来就所有php的请求都进行addslashes。这样会破坏原始的数据。也会污染入库的数据。所以addslashes 是在迫不得或者说没有数据库上下文的时候在使用。但是这种情况下使用的意义在何处?
参考文章
http://book.51cto.com/art/201204/331330.htm
http://www.2cto.com/kf/201206/137796.html
http://php.net/manual/zh/function.addslashes.php
http://php.net/manual/zh/function.mysql-real-escape-string.php
http://www.2cto.com/kf/201206/137796.html