我很想知道,如果在用户提交表单时已经过滤了正在检索的数据,是否有必要从MySQL服务器转义输出。
例:
1.用户提交一个带有博客评论的表单
2.在表单提交时,在将数据发送到MySQL服务器之前,使用FILTER_SANITIZE_SPECIAL_CHARS
过滤其输入以防止注入攻击
3.数据发布到服务器后,用户将被重新路由到另一个屏幕,在那里他们可以查看他们的评论
4.从服务器检索其注释(已存储已过滤的输入)时,是否还必须转义此输出?
这是我的主要问题。我正在从表单(用于博客文章)中获取用户输入,使用FILTER_SANITIZE_SPECIAL_CHARS
对其进行清理,然后将其发布到MySQL服务器。如果我从服务器检索此信息并以html格式显示,则没有问题。但是,我一直在读,你应该总是逃避服务器的输出。所以我用htmlspecialchars()
转发了同一个帖子。现在,我有一个问题,即所有特殊字符(包括括号,以及用户在其帖子中使用的任何引号)都以其转义的html格式返回。不是用户友好的。
最好的解决方法是什么,或者如果它来自服务器并且已经在用户输入上进行了清理,它是否甚至需要转义输出?
答案 0 :(得分:4)
清理不与转义相同,你应该确保不要混淆两者。
清理正在删除不需要的输入。也就是说,如果用户在其输入中添加了<script>
标记,并且您不希望其输入包含<script>
标记,则删除该<script>
标记将进行清理。清理是不转义输出上下文的数据。
转义正确编码输出上下文的数据。例如,为防止HTML注入,您可以致电htmlspecialchars()
将&
正确编码为&
。为防止SQL注入,您可以使用mysqli::real_escape_string()
将'
转换为\'
。 (虽然使用预准备语句/参数化查询以防止不必担心sql注入或转义,但高度更可取。)
重要,转义是特定于上下文的。您用于HTML的转义不一定对SQL有效或足够(反之亦然,或任何其他输出上下文)。
FILTER_SANITIZE_SPECIAL_CHARS
的问题在于它命名不佳:它只在一个步骤中执行,这会让您的数据库感到困惑(因为您的数据库现在有html编码的数据) ,并且输出容易混淆(因为现在你已经转义了很容易被多次转义的数据)。
相反,您应该明确区分您的清理和逃避工作。 仅清理您不想要保留的输入数据。 仅在输出上转义数据,并根据其正确的输出上下文。
您希望在数据库中存储原始(预输出转义)数据的原因是,如果您需要输出到不同的上下文(例如,现在您需要输出JSON输出,或者您需要把它写到一个文件,或实际看到原始数据是什么),你不需要首先解开它。 (如果你真的需要,你可以合理地将一个预先转发的副本存储在一个单独的列中,但是你应该始终可以获得原始数据。)它还使规则变得简单:始终清理输入;总是逃避输出。