问题 为什么filter_input()不完整?


我目前正在基于PHP的CMS上工作很多,而我正处于这种状态时,我希望将用户输入的所有处理和清洁工作转移到一个中心位置。 (目前,这里是$ _REQUEST,$ _GET,等等)。

我非常喜欢filter_input(),并希望将它用于基本的卫生设施,但我不清楚这个功能是否真的是生产就绪。例如, 文件 为$ type命名以下参数

INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV, INPUT_SESSION (not implemented yet) and INPUT_REQUEST (not implemented yet).

该函数自5.2.0以来就存在,为什么还没有实现两个关键元素呢?如果我想从$ _REQUEST获取数据,则必须使用用户提供的注释中的解决方法。这有什么特别的原因吗?这个功能还处于某种形式吗?作为处理传入数据的第一个调用,它是否值得信赖?

也许熟悉PHP开发过程的人可以对此有所了解。


8667
2017-11-27 17:21


起源

并且在2015年仍然没有实现$ _SESSION,至少没有检查其他人,但我只是再次拿起php球,但filter_var是一个解决方法。 - Chris
INPUT_SESSION 和 INPUT_FILES 没有实施(虽然 $_FILES 提出了一个多维用例,默认情况下与其他用例不同)。使用 filter_var_array() 对于 $_SESSION。我可能也会注意到,也没有“INPUT_DATABASE”,但你仍然有责任。再试一次吧 filter_var_array()。 - Anthony Rutledge


答案:


我想将用户输入的所有处理和卫生移动到一个中心位置

是的,那将是多么可爱。它无法完成。这不是文本处理的工作方式。

如果要将文本从一个上下文插入另一个上下文,则需要使用正确的转义。 (mysql_real_escape_string用于MySQL字符串文字,htmlspecialchars用于HTML内容,urlencode用于URL参数,其他用于特定上下文)。在进行过滤时,在脚本开始时,您不知道输入结束的位置,因此您不知道如何逃避它。

也许一个输入字符串既可以进入数据库(需要进行SQL转义),也可以直接进入页面(需要进行HTML转义)。这两种情况都没有逃脱。您可以一个接一个地使用两个转义符,但HTML中的值将出现奇怪的反斜杠,数据库中的副本将充满&符号。几轮这种错误的编码,你得到的情况是每次你编辑的东西,长串 \\\\\\\\\\\\\\\\\\\\ 和 & 出来。

在开始时一次安全过滤的唯一方法是完全删除所有需要转义的字符 任何 您将要使用它们的上下文。但这意味着您的HTML中没有撇号或反斜杠,数据库中没有符号或小数字,并且可能还有其他一些不友好的标点符号。对于一个不带任意文本的简单网站,你可能会侥幸逃脱。但通常不会。

因此,只有当一种文本进入另一种文本时,您才能逃脱。避免此问题的最佳策略是尽可能避免将文本连接到其他上下文中,例如通过使用参数化查询而不是SQL字符串构建,并定义 echo(htmlspecialchars()) 具有漂亮的短名称的函数可以减少输入的工作量,或者使用默认情况下HTML转义的替代模板系统。


8
2017-11-27 17:43



你确实写了很长的答案(虽然很好的解释)。 - C. Ross
@bobince:我说如果你知道你在脚本中需要什么,那么它可以在一定程度上完成,以及2.)将已消毒的变量标记为它们是什么。我已经分享了我所知道你所谈论的内容。\\\\\\\\\\\\\ :)我的主要目标是让一个基本的“安全检查点”具有一组定义的检查,而不是从代码中的数组中提取内容。 - Pekka 웃
一个简单的解释是过滤/清理只是数据需要经历的过程的一部分。清理数据仍然需要转义。例如无论多么有效,您都不会将电子邮件地址不加引号放入SQL查询中。 - Ben James
啊,好吧,我想我对“sanitisation”这个词有点过分敏感,以及它通常如何应用于PHP。过滤器函数是一堆杂乱的无关字符串格式化函数,其中一些对验证很有用,但其中一些非常不适合输入阶段。我同意这有点粗糙。虽然如果你可以使用INPUT_POST | INPUT_GET | INPUT_COOKIE(谁想要将cookie转换成表格文件?),就不需要INPUT_REQUEST了,但实现它似乎微不足道。由于过滤器从PECL转移到内置,因此似乎没有太多的发展。 - bobince
我倾向于观察 消毒 删除位,和 证实 检查位。我看 逃逸 在上下文之间转换比特。我创建了Sanitizer(带有输入源的子类),Validator(带输入源的子类),Escaper和Cipher类。一切都不会发生在一个地方,但至少它是模块化的。除参数化查询外,我还提倡使用PDO存储过程。数据库中的两个用户权限系统(DEFINER / INVOKER)也很有意义。 - Anthony Rutledge


“输入过滤”或“卫生”是一个荒谬的想法。远离它。

解释和进一步讨论

使用PHP清理用户输入的最佳方法是什么?

我还应该做些什么来消毒用户输入?


4
2017-11-27 18:32



请阅读上面的bobince我的讨论。 - Pekka 웃


在编程中,您必须尽可能限制输入。这也适用于数据源。 $ _REQUEST包含$ _GET,$ _POST和$ _COOKIE中的所有内容,这可能会导致问题。

例如,如果您的CMS插件在其中一个插件中引入了一个新的特殊键,恰好在另一个插件中作为一个有意义的键存在,会发生什么?

所以不要使用$ _REQUEST。使用$ _GET,$ _POST或$ _COOKIE,以适合您的方案为准。 这是一个很好的做法,尽可能严格,这与PHP无关,但与编程一般。


3
2017-11-27 17:39



$ _REQUEST的有效点,但是他们应该这样说,而不是让它未实现。 - Pekka 웃