我有一个表单,除其他外,接受上传的图像并将其粘贴到数据库中.以前我有一个过滤POSTed数据的功能基本上是:
function processInput($stuff) {
$formdata = $stuff;
$formdata = htmlentities($formdata, ENT_QUOTES);
return "'" . mysql_real_escape_string(stripslashes($formdata)) . "'";
}
Run Code Online (Sandbox Code Playgroud)
当努力修复一些未正确转换的怪异实体时,我将功能更改为(所有改变的是我在htmlentities中添加'UTF-8'位):
function processInput($stuff) {
$formdata = $stuff;
$formdata = htmlentities($formdata, ENT_QUOTES, 'UTF-8'); //added UTF-8
return "'" . mysql_real_escape_string(stripslashes($formdata)) . "'";
}
Run Code Online (Sandbox Code Playgroud)
现在图片无法上传.
会导致什么?只需删除"UTF-8"位即可正确上传图像,但用户放入系统的某些MS Word实体会显示为乱码.到底是怎么回事?
**编辑:因为我无法做太多改变这个野兽的代码我能够通过使用htmlspecialchars()而不是htmlentities()拍打一个bandaid,这似乎至少在转换像引号这样的东西时保持图像数据不变bobince的建议非常好,但在这种情况下,我现在无法花费时间来修复这个项目中混乱的遗留代码.我处理的大部分内容都是面向对象和基于框架的,但现在我亲眼看到人们在PHP中谈论"意大利面条代码"时的意思.
function processInput($stuff) {
$formdata = $stuff;
$formdata = htmlentities($formdata, ENT_QUOTES);
return "'" . mysql_real_escape_string(stripslashes($formdata)) . "'";
}
Run Code Online (Sandbox Code Playgroud)
此函数表示对字符串处理的基本误解,这是PHP程序员常见的一种.
SQL转义,HTML转义和输入验证是三个独立的函数,可以在脚本的不同阶段使用.尝试一气呵成是没有意义的; 它只会导致在脚本的其他部分中使用时对任何一个进程造成"特殊"的字符.您可以尝试修改此功能以尝试修复应用程序的一部分中的修改,但是您将破坏其他内容.
为什么图像被破坏了?嗯,通过什么路径图像数据从$_FILES临时上传文件到数据库,并不是很清楚.如果此功能涉及任何一点,它将完全破坏图像文件的二进制内容.反斜杠被删除和HTML转义...没有图像可以存活.
mysql_real_escape_string用于转义一些文本以包含在MySQL字符串文字中.在使用插入文本创建SQL字符串文字时,应始终使用它,而不是全局应用于输入.因为输入中的某些内容不会立即或仅单独存储到数据库中.例如,如果您echo是HTML页面的输入值之一,当它包含像这样的字符时,您会发现它中有一堆不需要的反斜杠'.这就是你最终得到的页面充满了失控的反斜杠.
(即使这样,参数化查询通常比手动字符串黑客更好mysql_real_escape_string.它们隐藏了字符串逃逸的细节,所以你不会被它们弄糊涂.)
htmlentities用于转义包含在HTML页面中的文本.它应该在PHP的输出模板位中始终使用.在所有输入上全局运行它是不合适的,因为不是所有内容都会在HTML页面中或仅在HTML页面中结束,并且很可能它首先会在您绝对不希望加载的情况下进入数据库的<和&垃圾让你的文字无法搜索或可靠的子串.
(即使这样,htmlspecialchars通常也是优选的,htmlentities因为它只编码真正需要它的字符.htmlentities将添加不必要的转义,除非你告诉它正确的编码它也将完全搞乱你所有的非ASCII字符.htmlentities应该几乎永远不会用过的.)
至于stripslashes......好吧,你有时需要将它应用于输入,但只有当白痴magic_quotes_gpc选项打开时.你肯定不应该一直应用它,只有当你检测到时才会应用它magic_quotes_gpc.它很久就被弃用了,幸好它已经消失了,所以如果你发现它被打开了,那么用一条错误消息轰炸可能就好了.然后你可以把整件事processInput扔掉.
总结一下:
在开始时,不进行全局输入处理.如果您愿意,可以在此处执行特定于应用程序的验证,例如检查电话号码只是数字,或者从文本或其他内容中删除控制字符,但此处不应该发生转义.
在使用字符串文字进行SQL查询时,在进入字符串时对值使用SQL-escaping : $query= "SELECT * FROM t WHERE name='".mysql_real_escape_string($name)."'";. 您可以使用较短的名称定义一个函数来执行转义以节省一些输入.或者,更可读的是参数化.
使用输入或数据库或其他地方的字符串进行HTML输出时,请使用HTML-escaping,例如:<p>Hello, <?php echo htmlspecialchars($name); ?>!</p>.同样,您可以使用短名称定义一个函数echo htmlspecialchars来保存键入.