php - "set names"vs mysqli_set_charset — 除了影响 mysqli_escape_string,它们是否相同?

标签 php mysql security encoding libmysql

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_charsetmysql_real_escape_string (和 friend )函数中使用。因此,如果你不使用这些函数,那么你可以考虑两个等价的。

让我们走源:

  1. Userland 函数 mysql_set_charsetmysqli_set_charset 调用...
  2. 引擎函数mysql_set_character_set调用...
  3. 引擎宏mysqlnd_set_character_set,定义为:

    #define mysqlnd_set_character_set(conn, cs)\ ((conn)->data)->m->set_charset((conn)->data, (cs)))

    并扩展到...

  4. 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_charsetmysql_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/

相关文章:

php - 检查数据库中复选框的值

php - 数组似乎没有保存数据

php - 在android中将php数组分成单独的Json响应

php - 安全使用 ImageMagick 转换

javascript - Ajax提交由PHP do-while循环动态生成的表单

php - 将Mysql程序转换为PHP代码

php - 预订系统 php mysql

mysql - 谷歌地图 API : Get zipcode

javascript - 使用安全 cookie 存储的 JWT 无状态登录 : how to implement log out?

security - 如何在 Silex 中对密码进行编码?