如果Web应用程序获取用户输入或参数,我们应该在验证时执行哪些必要且最重要的事情?

时间:2010-10-21 08:10:47

标签: php asp.net web-applications web

我一直在考虑网页上的任何类型的验证(PHP或ASP,无所谓),但从未找到一个好的和准确的答案。

例如,我有一些GET - 参数,它定义了一个像DESC或ASC这样的SQL查询。 (SQL-Injection?)

或者我有一个用户评论功能,其中数据也保存在数据库中。

是否应该检查数据中的HTML标签?是否应该在将其添加到数据库或在页面上显示之前完成验证?

我正在搜索ToDo,它应始终使用“outside”提供的任何数据执行。

感谢。

3 个答案:

答案 0 :(得分:1)

如果您正在使用PDO,请务必使用预准备语句 - 这些语句会自动清理传入数据。

如果使用mysql_ *函数,请先通过mysql_real_escape_string运行每个变量。

您还可以进行验证,例如确保变量是可接受范围之一:

$allowed_values = array('name', 'date', 'last_login')
if(in_array($v, $allowed_values)) {
    // now we can use the variable
}

答案 1 :(得分:1)

很好地了解您对用户的要求。

您希望他们指定升序/降序吗?这是一个枚举(或布尔值),不是SQL查询的一部分:

$query = "SELECT [...] ORDER BY field " . escape($_GET['sortOrder']); //wrong

无论您逃脱多少并清理其字符串,这都是错误的,因为这不是验证枚举的方法。比较:

if ($_GET['sortOrder'] == 'desc') {
    $ascending = false;
} else {
    $ascending = true;
}

if ($ascending) {
    ...
} else {
    ...
}

...这不保证讨论字符串转义或SQL注入,因为用户只需要是/否(或升序/降序)答案。

您希望他们输入评论吗?为什么禁止使用HTML标签?如果用户想要输入HTML代码怎么办?

同样,你想要的是“文本......任何文本,最大长度为1024个字符*”。这与SQL或注入有什么关系?没什么:

$text = $_POST['commentText'];

if (mb_strlen($text, ENCODING) <= 1024) {
    //valid!
}

数据库中的值应反映用户逐字输入的内容;没有翻译,没有逃脱。假设您正在剥离所有HTML&lt; tags&gt;来自评论。当您决定以JSON格式在某处发送评论时会发生什么?你也剥离了JSON控制字符吗?其他一些格式怎么样?如果HTML引入了一个名为“:)”的标签,会发生什么?你是否在你的数据库中绕过所有评论的笑脸?

答案是否定的,因为您不希望用户使用HTML安全,JSON安全,某些奇怪的格式与表情符号安全的输入。您希望文本最多1024个字符。检查一下。存储它。

现在,显示部分比较棘手。为了显示:

<b>I like HTML "tags"
在HTML中,您需要编写如下内容:

&lt;b&gt;I like HTML &quot;tags&quot;

在JSON中,您可以这样做:

{ "I like HTML \"tags\" }

这就是为什么你应该使用语言工具来逃避使用它时的数据

SQL当然也是如此,这就是为什么在PHP中使用mysql_query()这样的简单查询函数时应该转义数据的原因。 (另一方面,参数化查询,你应该真正使用它,不需要转义。)

摘要

非常清楚你想要什么作为输入,记住你几乎从不需要,比如“HTML安全文本”。对此进行验证。在需要时转义,意味着在发送到浏览器时转义HTML,在发送到数据库时转移SQL,等等。


*:您还应该定义“字符”在这里的含义。例如,UTF-8可以使用多个字节来编码代码点。 “字符”是指“字节”还是“Unicode代码点”?

答案 2 :(得分:0)

您正在谈论两种数据卫生。一种是将用户生成的数据放入数据库,另一种是将用户生成的数据放在网页上。对于前者,您应该遵循亚当的建议。对于后者,您应该查看htmlspecialchars

不要将这两者混合在一起,因为它们完全不同。为此目的,卫生应该只在最后一刻进行。在更新数据库之前使用adam的建议。在回显数据之前使用htmlspecialchars。在将数据添加到数据库之前,对数据使用htmlspecialchars。

您可能还想查看Stackoverflow,因为过去曾多次询问和回答过这类问题。