你是如何解析它的,你对结果做了什么?
如果您编写构建 SQL 语句的代码,那么您很容易受到 SQL 注入的攻击。
假设你这样写:
set @myquery = 'select customer_name from customer where customer_id = ''' + @custid + ''''
execute (@myquery)
假设您最终从用户输入获得@custid,比如表单上的文本框。
如果用户进入
42
那么查询就变成了
select customer_name from customer where customer_id = '42'
酷。大概这就是你想要的。
但假设用户输入
42'; update customer set balance_due = 0 where customer_id = '42
现在你的查询变成了
select customer_name from customer where customer_id = '42'; update customer set balance_due = 0 where customer_id = '42'
并且客户刚刚将应付余额归零。或者他可能会删除整个表等。
故事的寓意是,永远不要使用用户输入动态构建 SQL 查询。它使用户能够对您的数据库执行任何他们想做的事情。
正确的做法是:
select customer_name from customer where customer_id = @custid
然后,如果用户尝试使用 SQL 注入,他们只会在记录上创建一个 not-found,因为他们输入的 SQL 字符串不是有效的客户 ID。 (或者如果你不做任何类型检查,他们可能会得到一个数据转换错误。这也很糟糕,你应该防止这种情况,但不如 SQL 注入那么糟糕。)
避免动态构建 SQL 语句。尽可能将值作为参数传入。
好的,有时您只需要动态构建语句。我能想到的最常见的情况是一个选择标准屏幕,用户可以在其中输入 10 个不同标准的值——日期在这个范围内,名称包含这个,数量小于那个等等——但每个条件都是可选的,如果用户没有输入值,那么您不希望将该测试作为查询的一部分。因此,有数百万种可能的组合,您希望即时将查询组合在一起。这很好,但不要在动态构建查询时插入值。插入参数,然后设置参数。
如果值是在程序中生成而不是从用户输入中生成的,并且您绝对确定这些值永远不会包含 SQL 注入文本,那么将值构建到 SQL 中是安全的。我这样做的唯一一次是当我有固定的硬编码值时。就像我可能构建的代码说“类型 = 1”或者它可能说“类型 = 2”,并且 1 和 2 在程序中是硬编码的,而不是用户输入。如有疑问,请创建参数。