Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/246.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php &引用;“设置名称”;vs mysqli_set_charset—;除了影响mysqli_escape_字符串之外,它们是否相同?_Php_Mysql_Security_Encoding_Libmysql - Fatal编程技术网

Php &引用;“设置名称”;vs mysqli_set_charset—;除了影响mysqli_escape_字符串之外,它们是否相同?

Php &引用;“设置名称”;vs mysqli_set_charset—;除了影响mysqli_escape_字符串之外,它们是否相同?,php,mysql,security,encoding,libmysql,Php,Mysql,Security,Encoding,Libmysql,它需要使用/而不是直接的MySQL查询 经常引用的原因是集合名称不安全,因为用于/将仅通过调用mysql\u set\u charset/mysqli::set\u charset来设置编码。(引用的另一个原因是PHP文档称其“不推荐”。) 但是,如果我们使用预先准备好的语句和或除了MySQL\u real\u escape\u string/mysqli::real\u escape\u string/ 除了影响mysql\u real\u escape\u string/mysqli::re

它需要使用/而不是直接的MySQL查询

经常引用的原因是
集合名称
不安全,因为用于/将仅通过调用
mysql\u set\u charset
/
mysqli::set\u charset
来设置编码。(引用的另一个原因是PHP文档称其“不推荐”。)

但是,如果我们使用预先准备好的语句和或除了MySQL\u real\u escape\u string/
mysqli::real\u escape\u string
/

除了影响
mysql\u real\u escape\u string
/
mysqli::real\u escape\u string
/
mysqli\u escape\u string
的编码外,
set name
mysql\u set\u charset
/
mysqli::set\u charset
之间有什么区别吗?

  • 在将引号(和其他字符)放在引号内之前,对其进行转义。否则,引号将导致语法错误
  • 建立客户端中字节的编码。这样,
    插入
    /
    选择
    将知道如何在写入/读取期间更改字节
第一个需要转义撇号和双引号,因为它们都是MySQL语法中字符串的可接受引号。然后,转义字符本身需要转义。这3个字符足以满足必须使用的应用程序。但是,如果您试图转义
BLOB
(例如.jpg),各种控制字符可能会导致问题。您最好先转换为十六进制,然后使用
UNHEX()
,以避免出现问题。注意:这里没有提到有关字符集的内容。如果您没有处理
blob
,那么可以使用PHP的
addslashes()

第二项的目的是说“这个字节流是这样编码的(utf8/latin1/etc)”。它的唯一用途是在存储/获取的列的
字符集
和客户机中所需的编码(PHP等)之间进行转换。它由各种语言以各种方式处理。对于PHP:

  • mysql.*
    ——不要使用此接口;它已弃用,不久将被删除
  • mysqli.*
    --
    mysqli::set\u字符集(…)
  • PDO--
    新的PDO('…;字符集=UTF8',…)
set\u charset()?我不知道。但这不重要
SET name
显然不能,因为它是一个MySQL命令,对PHP一无所知

htmlentities()
是该领域的另一个PHP函数。它将8位代码转换为
&
实体。这不应该用于MySQL。这只会掩盖其他问题。仅在涉及HTML的特定情况下使用它,而不是PHP或MySQL

目前使用的唯一合理的
字符集是ascii、拉丁文1、utf8和utf8mb4。在“控制”区域中没有“字符”。Sjis和其他一些字符集可以。这种对控制字符的混淆可能是存在真实转义字符串的原因

结论:

在我看来,您需要两种机制:一种用于转义,另一种用于在客户机中建立编码。它们是分开的


如果将它们捆绑在一起,PHP手册就无法提供任何令人信服的理由来选择一种方法而不是另一种方法。

mysql:整个接口都不推荐使用,所以根本不要使用任何接口(PHP7删除了接口)

mysqli(和PDO)已经准备好了一些语句,这些语句不需要(也不需要)使用
real\u escape\u string
。 ->因此,如果您只使用mysqli和prepared语句:不用担心如何设置字符集

因为您关心安全性:我认为不使用预先准备好的语句没有什么意义

一旦使用mysqli准备好的语句,唯一的方法就是使用
$mysqli->set\u charset()
,因为您不能再简单地将多个sql语句串联在一个字符串中

因此,了解这种差异的问题最多是学术性的,与现实生活无关

总之:

  • mysql:根本不用

  • mysqli:使用准备好的语句,因此使用
    set\u charset()
    方法
    此外:一旦使用准备好的语句,就不再需要真正的\u escape\u字符串

  • 或者——当然——使用PDO及其方法


在连接上调用
SET name
相当于调用
SET\u charset
,前提是您既不调用
get\u charset
也不调用
mysql\u real\u escape\u string
(和朋友)。


当您调用
set\u charset
时,PHP做两件事。首先,它调用连接上的
SET name
。其次,它会记住你设置的字符集。该状态信息稍后仅用于
get\u charset
mysql\u real\u escape\u string
(和friends)函数中。因此,如果你不使用这些函数,那么你可以考虑这两个等价物。

让我们了解一下来源:

  • Userland函数
    mysql\u set\u charset
    mysqli\u set\u charset
    调用
  • 引擎函数
    mysql\u set\u character\u set
    调用
  • 引擎宏mysqlnd\u set\u character\u set
  • ,定义为:

    #定义mysqlnd\u集\u字符集(conn,cs)\
    ((conn)->data)->m->set_字符集((conn)->data,(cs))

    并扩展到

  • MYSQLND\u方法(MYSQLND\u conn\u data,set\u charset)
    以下代码(编号供讨论,这些不是实际的源代码行号):


  • 如您所见,PHP在连接本身(第3行)上调用
    SET name
    。PHP还跟踪刚刚设置的字符集(第10行)。comme
     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   }
    
    SET character_set_client = charset_name;
    SET character_set_results = charset_name;
    SET character_set_connection = charset_name;