MySQL在卷曲(智能)引号上窒息

Dis*_*oat 8 php mysql quotes smart-quotes

我正在从表单中将一些数据插入到数据库中.我正在使用addslashes以逃避文本(也试过mysql_real_escape_string相同的结果).

常规报价已转义,但其他一些报价则没有.例如,字符串:

荷马的血液成为Moe新啤酒的秘密成分.

转换为:

荷马的血液成为Moe新啤酒的秘密成分.

我不认为卷曲引用无关紧要,但只有这个文本被插入到数据库中:

荷马的血液成为萌的秘密成分

所以PHP认为卷曲的引用很好,但MySQL正在丢失字符串.MySQL虽然没有给出任何错误.

cha*_*aos 7

我会查找Web界面中使用的字符编码与数据库级别使用的字符编码之间的不匹配.例如,如果您的Web界面使用UTF-8,并且您的数据库使用的是默认的MySQL编码latin1,那么您需要设置表格DEFAULT CHARSET=utf8.

mysql_real_escape_string()顺便使用或mysqli. addslashes()不是对SQL注入足够的保护.

  • 啊,好的 IMO与魔术引号唯一值得做的就是删除它们,所以你只需要`stripslashes()`.:) (2认同)

Vol*_*erK 7

'moe's是你的示例字符串中唯一的字符,如果该字符串是latin1编码但你的mysql服务器需要utf8,那么该字符将无效.

简单演示:

<?php
function foo($s) {
    echo 'len=', strlen($s), ' ';
  for($i=0; $i<strlen($s); $i++) {
    printf('%02X ', ord($s[$i]));
  }
  echo "\n";
}

 // my file is latin1 encoded and so is the string literal
foo('Moe’s');
// now try it with an utf8 encoded string
foo( utf8_encode('Moe’s') );
Run Code Online (Sandbox Code Playgroud)

版画

len = 5 4D 6F 65 92 73
len = 6 4D 6F 65 C2 92 73

因此问题是:你是否以"错误"编码的方式提供mysql服务器?
每个连接都有一个连接字符集,mysql服务器希望你的客户端(php脚本)发送在该字符集中编码的数据.您可以找到连接字符集的内容

SHOW VARIABLES LIKE '%character%'
Run Code Online (Sandbox Code Playgroud)

$mysql = mysql_connect('..', '..', '..') or die(mysql_error());
mysql_select_db('..', $mysql) or die(mysql_error());

$query = "SHOW VARIABLES like '%character%'";
$result = mysql_query($query, $mysql) or die(__LINE__.mysql_error());
while( false!==($row=mysql_fetch_array($result, MYSQL_ASSOC)) ) {
  echo join(', ', $row), "\n";
}
Run Code Online (Sandbox Code Playgroud)

这应该打印出类似的东西

character_set_client, utf8
character_set_connection, utf8
character_set_database, latin1
character_set_filesystem, binary
character_set_results, utf8
character_set_server, utf8
character_set_system, utf8
Run Code Online (Sandbox Code Playgroud)

character_set_connection, utf8指示"我的"连接字符集是utf8,即mysql服务器需要来自客户端(php)的utf8编码字符.什么是"你的"连接charset?

然后看一下参数字符串的实际编码,即如果你有

$foo = mysql_real_escape_string($_POST['foo'], $mysql);
Run Code Online (Sandbox Code Playgroud)

替换它

echo '<div>Debug hex($_POST[foo])=';
for($i=0; $i<strlen($s); $i++) {
    printf('%02X ', ord($_POST['foo'][$i]));
}
echo "</div>\n";
$foo = mysql_real_escape_string($_POST['foo'], $mysql);
Run Code Online (Sandbox Code Playgroud)

并检查输入字符串的实际编码是什么.它是打印92还是C2 92?