在存储数据之前对其进行清理可能意味着存储的数据与用户输入的数据不同 - 这是常见的做法吗?

Posted

技术标签:

【中文标题】在存储数据之前对其进行清理可能意味着存储的数据与用户输入的数据不同 - 这是常见的做法吗?【英文标题】:Sanitizing data before storing it might mean stored data is different to what the user entered - is that common practice? 【发布时间】:2020-12-23 16:45:12 【问题描述】:

背景

html 表单,例如供用户提交他们的业务详细信息,这些详细信息稍后将出现在法律文件中 - 因此数据需要准确。

提交到验证所有输入的 php 脚本。

如果所有输入都有效,它会清理数据并使用参数化查询将其写入数据库。

如果任何输入无效,它会重新显示表单。我的感觉是,用户希望此表单中填充他们最初输入的内容,并提供一些关于他们输入错误的反馈。然后,他们可以修改输入并重新提交表格。这意味着表单需要填充 unsanitized 数据(这将在显示之前被转义)。

到目前为止一切顺利。

问题

如果数据有效,则将其写入数据库。最佳做法似乎是在将数据发送到数据库之前对其进行清理。

这意味着写入数据库的数据可能与用户输入的数据不完全相同(例如,如果清理删除了一些“危险”字符)。

这对我来说似乎是一种糟糕的用户体验。

我正在使用 PHP,并且代码在 WordPress 框架中运行。 WP 有自己的清理功能,他们建议在使用之前始终清理输入。他们还建议使用 PHP 的清理功能。但似乎没有什么能解决在存储数据之前对数据进行清理可能导致保存的数据与用户输入的数据不同的问题。

问题

我想要描述在现实世界中用于解决此问题的方法?或者从比我更有经验的人那里得到一些反馈,这在现实世界中不是问题,通常的做法是清理数据并将其存储,而不需要进一步关注或反馈给用户。

我对可能解决方案的看法

更彻底的模式是将不卫生的数据视为无效数据,并向用户反馈他们的输入有什么问题。但这似乎不切实际,并且需要相当长的清理功能才能向用户提供任何具体和有用的反馈。它还使现有的 WP/PHP 清理功能有些无关紧要。

一种实际的折衷方案可能是将经过清理的数据与原始数据进行比较,然后简单地通知用户某些内容在保存之前已被清理...这样他们至少可以检查保存的数据以确保他们满意它。

感谢您的帮助。

结论

我接受的答案很有帮助,并引导我找到了针对我的特定用例的解决方案,但我想添加一些我自己的观点。

首先,在重新阅读 WP 文档时,我发现不建议在写入数据库之前进行验证和清理。它建议进行验证,但如果特定情况不需要严格验证,则建议清理输入可能更方便。它还说使用一个或另一个,而不是两者。所以我认为 WP 文档在这方面没有错,我只是误读了它。

其次,我不明白参数化查询对 SQL 注入如此有效。所以我认为在数据库查询中使用输入之前对其进行清理是一件明智的事情。不过好像没必要。

最后,我现在意识到这一切都与上下文有关......问题在于使数据安全以用于特定用途。从这个意义上说,并不是一种技术只适用于输入,而另一种技术只适用于输出。在对数据进行任何操作时,我需要考虑验证、清理或转义 - 例如将其写入数据库,在计算中使用它,将其打印到屏幕上,或将其注入 PDF 文档。在所有情况下,我只需要考虑如何确保特定用途的安全。清理“输入”可能是完全合适的——如果它快速简单,可以让数据安全地用于我需要做的任何事情,并且不会导致数据不准确。另一个例子是 WordPress 函数 esc_url_raw() ,手册中说它专门用于在数据库中存储 URL 时使用。因此,转义仅适用于“输出”的想法再次具有误导性。

我最终在将输入写入数据库之前对其进行了验证。我也不需要对其进行消毒。因此,如果它无效,我会告诉用户。如果它有效,它将以其原始形式写入数据库。我在将其显示给用户之前将其转义。

【问题讨论】:

【参考方案1】:

最佳实践似乎是在将数据发送到数据库之前对其进行清理。

这是一个常见的误解。清理应该只对正在输出的数据执行,例如防止 XSS,即使这样也只能作为最后的手段。正是因为它可以不可逆地破坏原始数据。

验证是您的第一道防线。确保数据格式正确,并且在其上下文中有效——仅此而已;不找特殊字符,不要过分热心。如果它无效 - 拒绝它,不要试图从中挽救“好的”部分。

然后,当存储在数据库中时,您只需要使用参数化查询 - 这对 SQL 注入 100% 有效。如果您没有在上一步中破坏数据,则将其存储为原始形式。

最后,当数据被输出时,你应该在适当的上下文中转义特殊字符,以便正确呈现;或者如果您别无选择,则对其进行清理(即上下文不清楚,因此您无法进行适当的转义)。

【讨论】:

谢谢,但是...你说清理是关于输出的,但是 WordPress 插件手册developer.wordpress.org/plugins/security/securing-input 中的这个页面有一个关于“保护(清理)输入”的完整部分,这就是我的具体内容我在询问...清理输入。我在清理(转义)输出时没有问题。 正如我所说,这是一种常见的误解。可悲的是,WP 手册在这方面也是错误的。【参考方案2】:

看起来您很担心用户感受,这很好。您可以做的事情很少。 使用 html 表单 pattern - 肯定没有人需要像 < > & $ " ... 这样的符号 - 用 pattern 排除这个,使用 css :invalid:invalid:focus 在提交之前通知用户是否有问题。这非常容易和简单。 比 php 进一步验证和 WP 卫生。 您可以使用中间状态 - 在“清洗”之后 - 使用 2 个按钮显示最终版本(无输入) - 保存或更正 - 让用户决定,我们大多数人不喜欢这种重复“你确定吗?点击提交意味着提交?” - 但也许有如此相关的内容,用户希望有最后的机会,他们希望看到最终版本(没有输入、复选框等)。 现在您将接受的版本放入数据库(已准备好)。 将原始数据与洗过的数据进行比较是不切实际的,老实说,这很糟糕——用户不会是编码员——他们只是无法正确理解“我们对你的答案进行了清理,现在它们缩短了 345 个字符。抱歉给您带来不便” 不用太担心 ...有一个德国姓氏 'Ei' - 只有 2 个字符,所以模式不能超过 2 个。

【讨论】:

以上是关于在存储数据之前对其进行清理可能意味着存储的数据与用户输入的数据不同 - 这是常见的做法吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何在将图像上传到 Firebase 存储之前对其进行压缩?

在存储到数据库之前或渲染之前清理 HTML? (ASP.NET 中的反 XSS 库)

何时最好清理用户输入?

使用 Wordpress,有人可以告诉我清理输入的最佳方法吗?

存储信用卡信息 [重复]

在存储到数据库之前加密密码?