是的,您通常是正确的。
一条数据只有在“使用”时才是危险的。只有在使用的上下文中具有特殊含义时,它才是危险的。
例如,<script> 只有在输出到 HTML 页面时才具有危险性。
Robert'); DROP TABLE Students;-- 只是危险的when used in a database query。
通常,您希望尽可能晚地使这些数据“安全”。例如当作为 HTML 输出到 HTML 页面时的 HTML 编码,并在插入数据库时进行参数化。这样做的一大优势是,当稍后从这些位置检索数据时,它将以其原始、未经处理的格式返回。
因此,如果您在输入字段中有值 A&B O'Leary,它将被编码如下:
<input type="hidden" value="A& O'Leary" />
如果将其提交给您的应用程序,您的编程框架将自动为您将其解码回A&B O'Leary。与您的数据库相同:
string name = "A&B O'Leary";
string sql = "INSERT INTO Customers (Name) VALUES (@Name)";
SqlCommand command = new SqlCommand(sql);
command.Parameters.Add("@Name", name];
简单。
此外,如果您需要以纯文本形式向用户提供任何输出,您应该从数据库中检索它并将其吐出。或者在 JavaScript 中 - you just JavaScript entity encode (尽管出于复杂性的原因最好避免 - 我发现如果我只输出到 HTML 然后从 DOM 中读取值更容易保护)。
如果您提前对其进行了 HTML 编码,那么要输出到 JavaScript/JSON,您首先必须将其转换回来,然后再对其进行十六进制实体编码。它会变得一团糟,一些开发人员会忘记他们必须先解码,并且到处都有 &s。
您可以使用验证作为额外的防御,但它不应该是第一个停靠港。例如,如果您要验证英国邮政编码,您可能希望将大写和小写字母数字字符列入白名单。您的应用程序将拒绝或删除任何其他字符。这可以减少您的应用程序上发生 SQLi 或 XSS 的机会,但是在您需要输入以包含对输出上下文具有特殊含义的字符(" '<> 等)时,这种方法会失败。例如,在 Stack Overflow 上,如果他们不允许使用此类字符,您将阻止问题和答案包含代码 sn-ps,这几乎会使网站变得毫无用处。