它 seems to be common knowledge使用 mysql_set_charset
/mysqli::set_charset
而不是直接的 MySQL 查询 set names
.
经常提到的原因是 set names
不安全,因为 mysql_real_escape_string
使用的编码/mysqli::real_escape_string
只能通过调用 mysql_set_charset
/mysqli::set_charset
来设置。 (引用的另一个原因是 PHP 文档说它“不推荐”§。)
但是,如果我们使用准备好的语句和或 other means of escaping,使用直接 MySQL 查询 set names
是否安全?除了 mysql_real_escape_string
/mysqli::real_escape_string
/mysqli_escape_string
?
除了影响mysql_real_escape_string
/mysqli::real_escape_string
/mysqli_escape_string
的编码,set names
有什么区别吗? code> vs mysql_set_charset
/mysqli::set_charset
?
最佳答案
在连接上调用 SET NAMES
等效于调用 set_charset
,前提是您既不调用 get_charset
也不调用 mysql_real_escape_string
(和 friend )。
当您调用 set_charset
时,PHP 会做两件事。首先,它在连接上调用 SET NAMES
。其次,它会记住您设置的字符集。该状态信息稍后仅在 get_charset
和 mysql_real_escape_string
(和 friend )函数中使用。因此,如果你不使用这些函数,那么你可以考虑两个等价的。
让我们走源:
- Userland 函数
mysql_set_charset
和mysqli_set_charset
调用... - 引擎函数
mysql_set_character_set
调用... 引擎宏
mysqlnd_set_character_set
,定义为:#define mysqlnd_set_character_set(conn, cs)\ ((conn)->data)->m->set_charset((conn)->data, (cs)))
并扩展到...
MYSQLND_METHOD(mysqlnd_conn_data, set_charset)
其中contains以下代码(编号用于讨论,这些不是实际的源代码行号):
1 if (PASS == conn->m->local_tx_start(conn, this_func)) {
2 char * query;
3 size_t query_len = mnd_sprintf(&query, 0, "SET NAMES %s", csname);
4
5 if (FAIL == (ret = conn->m->query(conn, query, query_len))) {
6 php_error_docref(NULL, E_WARNING, "Error executing query");
7 } else if (conn->error_info->error_no) {
8 ret = FAIL;
9 } else {
10 conn->charset = charset;
11 }
12 mnd_sprintf_free(query);
13
14 conn->m->local_tx_end(conn, this_func, ret);
15 }
如您所见,PHP 在连接本身上调用 SET NAMES
(第 3 行)。 PHP 还跟踪刚刚设置的字符集(第 10 行)。评论进一步讨论了 conn->charset
会发生什么,但足以说它最终只存在于 get_charset
和 mysql_real_escape_string
(和 friend ) .
所以,如果你不关心这个状态,并且你同意既不使用 get_charset
也不使用 mysql_real_escape_string
,那么你可以调用 SET NAMES
连接本身没有不良影响。
顺便说一句,我从来没有这样做过,但是使用 -DPHP_DEBUG=1
编译 PHP 似乎可以通过各种 DBG
宏进行大量调试。这对于查看您的代码如何通过此 block 可能很有用。
关于php - "set names"vs mysqli_set_charset — 除了影响 mysqli_escape_string,它们是否相同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26596294/