你如何通过 PHP 清理 $_GET -variables 中的数据?
我只清理 GET by 中的一个变量strip_tags。我不确定是否应该清理所有内容,因为上次将数据放入 Postgres 时,使用pg_prepare.
strip_tags
pg_prepare
您不会清理 $_GET 中的数据。这是 PHP 脚本中的常用方法,但它是完全错误的*。
您的所有变量都应保持纯文本形式,直到您将它们嵌入另一种类型的字符串中。没有一种形式的转义或“清理”可以涵盖您可能将值嵌入其中的所有可能类型的字符串。
因此,如果您将字符串嵌入到 SQL 查询中,则需要在退出时对其进行转义:
$sql= "SELECT * FROM accounts WHERE username='".pg_escape_string($_GET['username'])."'";
如果您将字符串吐出到 HTML 中,则需要将其转义:
Cannot log in as <?php echo(htmlspecialchars($_GET['username'], ENT_QUOTES)) ?>.
如果您按照不知道自己在做什么的人的建议,在一开始就对 $_GET 数组执行了这两个转义步骤:
$_GET['username']= htmlspecialchars(pg_escape_string($_GET['username']));
然后,当您的用户名中有“&”时,它会神秘地变成“&” 在您的数据库中,如果您的用户名中有一个撇号,它将在页面上变成两个撇号。然后,当您有一个包含这些字符的表单时,很容易在编辑它们时出现双重转义,这就是为什么这么多糟糕的 PHP CMS 最终会出现诸如“O\\ 的新书”之类的损坏文章标题的原因\\\\\\\'赖利”。
自然,每次发送变量时都要记住 pg_escape_string 或 mysql_real_escape_string 和 htmlspecialchars 有点乏味,这就是为什么每个人都想在脚本开头的一个地方(错误地)这样做。对于 HTML 输出,您至少可以通过定义一个具有 echo(htmlspecialchars(…)) 的短名称的函数来节省一些输入。
对于 SQL,最好使用参数化查询。对于 Postgres,有pg_query_params。或者实际上,正如您提到的那样准备好的陈述(尽管我个人认为它们不太容易管理)。无论哪种方式,您都可以忘记“清理”或转义 SQL,但如果您嵌入其他类型的字符串(包括 HTML),您仍然必须转义。
strip_tags() 不是处理 HTML 显示输入的好方法。过去它存在安全问题,因为浏览器解析器实际上对标签的解释比您想象的要复杂得多。htmlspecialchars() 几乎总是使用正确的东西,所以如果有人输入小于号,他们实际上会得到一个字面的小于号,并且不会发现一半的文本神秘地消失了。
(*:无论如何,作为解决注入问题的一般方法。当然,值得对特定字段进行特定于域的检查,并且您可以执行有用的清理任务,例如从提交的值中删除所有控制字符。但这是不是大多数 PHP 编码人员所说的清理。)