23

当我准备解决输入数据过滤和清理问题时,我很好奇是否有最佳(或最常用)的做法?在将数据插入数据库之前过滤/清理数据(HTML、JavaScript 等)是否更好,还是应该在准备以 HTML 显示数据时进行?

几点注意事项:

  • 我在 PHP 中执行此操作,但我怀疑此问题的答案与语言无关。但是,如果您有任何特定于 PHP 的建议,请分享!
  • 这不是为了数据库插入而转义数据的问题。我已经让 PDO 处理得很好。

谢谢!

4

6 回答 6

18

在显示用户提交的数据时,普遍接受的口头禅是“过滤输入,转义输出”。

我建议不要在进入数据库之前转义 html 实体等内容,因为您永远不知道 HTML 何时不会成为您的显示媒体。此外,不同类型的情况需要不同类型的输出转义。例如,在 Javascript 中嵌入字符串需要与在 HTML 中不同的转义。之前这样做可能会让自己陷入一种虚假的安全感。

因此,基本的经验法则是,在使用前进行消毒,并专门针对该用途进行消毒;不是先发制人。

(请注意,我不是在谈论转义 SQL 的输出,只是为了显示。请仍然转义为 SQL 字符串绑定的数据)。

于 2009-08-13T21:10:48.140 回答
12

我喜欢以原始形式拥有/存储数据。我只根据我使用它的位置来转义/过滤数据。

  • 在网页上 - 编码所有 html
  • 关于 sql - 杀死引号
  • 在 url - urlencoding
  • 在打印机上 - 编码转义命令
  • 在什么地方 - 为那份工作编码
于 2009-08-13T21:10:00.387 回答
7

您应该关心至少两种类型的过滤/清理:

  • SQL
  • HTML

显然,在将数据插入数据库之前/时必须注意第一个,以防止 SQL 注入。
但是你已经知道了,正如你所说,所以我不会多说。


另一方面,第二个问题是一个更有趣的问题:

  • 如果您的用户必须能够编辑他们的数据,那么以与他们最初输入数据相同的方式将其返回给他们是很有趣的;这意味着您必须存储“非 html-specialchars-escaped”版本。
  • 如果你想显示一些 HTML,你可能会使用HTMLPurifier之类的东西:非常强大......但是如果你在必须显示的每个数据上运行它可能需要太多资源......

所以 :

  • 如果您想显示一些 HTML,使用重型工具来验证/过滤它,我会说您需要将已经过滤/任何版本存储到数据库中,以免破坏服务器,每次重新创建数据被陈列
    • 但是您还需要存储“原始”版本(请参阅我之前所说的)
    • 在那种情况下,我可能会将两个版本都存储到数据库中,即使它需要更多的地方......或者至少使用一些好的缓存机制,而不是一遍又一遍地重新创建干净的版本。
  • 如果您不想显示任何 HTML,您将使用htmlspecialchars或等效的,这可能不是 CPU 消耗者...所以它可能并不重要
    • 您仍然需要存储“原始”版本
    • 但是在输出数据时转义可能没问题。

顺便说一句,如果用户在输入数据时使用 bbcode/markdown/wiki 之类的东西,并且您在 HTML 中呈现它,那么第一个解决方案也很好......
至少,只要它的显示频率高于更新频率 - 并且特别是如果您不使用任何缓存来存储干净的 HTML 版本。

于 2009-08-13T21:11:05.300 回答
6

如有必要,在将其放入数据库之前对其进行清理(即,如果您没有使用为您处理的数据库交互层)。在展示之前对其进行消毒以进行展示。

以目前不必要的引用形式存储东西只会导致太多问题。

于 2009-08-13T21:10:37.687 回答
6

我总是在将它们传递到需要逃脱的地方之前立即说逃脱。您的数据库不关心 HTML,因此在存储到数据库之前转义 HTML 是不必要的。如果您想要输出 HTML 以外的内容,或更改允许/禁止的标签,您可能需要做一些工作。此外,与流程的早期阶段相比,记住在需要完成时正确进行转义更容易。

还值得注意的是,HTML 转义字符串可能比原始输入长得多。如果我在注册表中输入日本用户名,原始字符串可能只有 4 个 Unicode 字符,但 HTML 转义可能会将其转换为“〹ल䡈穩”的长字符串. 然后我的 4 字符用户名对于您的数据库字段来说太长了,并且被存储为两个日文字符加上半个转义码,这也可能阻止我登录。

请注意,浏览器往往会在提交的表单中转义某些内容,例如非英文文本,并且总会有那个在任何地方使用日文用户名的聪明人。因此,您可能希望在存储之前实际取消转义HTML。

于 2009-08-13T22:00:12.980 回答
4

大多数情况下,这取决于您打算如何处理输入以及您的开发环境。

在大多数情况下,您需要原始输入。这样,您就可以根据自己的喜好调整输出,而不必担心丢失原始文件。这还允许您解决诸如输出损坏等问题。您总是可以看到您的过滤器有什么问题或客户的输入是错误的。

另一方面,一些简短的语义数据可以立即被过滤掉。1)您不希望数据库中有凌乱的电话号码,因此对于此类事情,清理一下可能会很好。2)您不希望其他程序员在没有转义的情况下意外输出数据,并且您在多道程序环境中工作。然而,在大多数情况下,原始数据比 IMO 更好。

于 2009-08-13T21:14:08.240 回答