这个存储过程可以安全地避免 SQL 注入吗?
此存储过程使用 sp_executesql 执行带参数的 sql。
sql注入安全吗?
create procedure ExecutePeopleFilter
(@lastNameFilter varchar(20),
@companyNameFilter varchar(20),
@ageFilter int,
@dateFilter datetime)
as
begin
declare @sql varchar(4000)
declare @params varchar(1000)
declare @whereClause varchar(1000)
set @whereClause = ''
if ISNULL(@lastNameFilter,'') <> ''
begin
if (LEN(@whereClause) <> 0) set @whereClause += ' and '
if (LEN(@lastNameFilter) < 20) set @lastNameFilter += '%'
set @whereClause += 'LastName like @lastName '
end
if ISNULL(@companyNameFilter,'') <> ''
begin
if (LEN(@whereClause) <> 0) set @whereClause += ' and '
if (LEN(@companyNameFilter) < 20) set @companyNameFilter += '%'
set @whereClause += 'CompanyName like @companyName '
end
if @ageFilter is not null
begin
if (LEN(@whereClause) <> 0) set @whereClause += ' and '
set @whereClause += 'Age = @age '
end
if @dateFilter is not null
begin
if (LEN(@whereClause) <> 0) set @whereClause += ' and '
set @whereClause += 'StartDate = @startDate '
end
set @sql = 'select FirstName, LastName, CompanyName, Age, StartDate
from People'
if (LEN(@whereClause) <> 0) set @sql += ' where ' + @whereClause
set @params = '@lastName varchar(20),
@companyName varchar(20),
@age int,
@startDate datetime'
execute sp_executesql @sql, @params,
@lastName = @lastNameFilter,
@companyName = @companyNameFilter,
@age = @ageFilter,
@startDate = @dateFilter
end
This stored proc executes sql with parameters using sp_executesql.
Is it safe from sql injection?
create procedure ExecutePeopleFilter
(@lastNameFilter varchar(20),
@companyNameFilter varchar(20),
@ageFilter int,
@dateFilter datetime)
as
begin
declare @sql varchar(4000)
declare @params varchar(1000)
declare @whereClause varchar(1000)
set @whereClause = ''
if ISNULL(@lastNameFilter,'') <> ''
begin
if (LEN(@whereClause) <> 0) set @whereClause += ' and '
if (LEN(@lastNameFilter) < 20) set @lastNameFilter += '%'
set @whereClause += 'LastName like @lastName '
end
if ISNULL(@companyNameFilter,'') <> ''
begin
if (LEN(@whereClause) <> 0) set @whereClause += ' and '
if (LEN(@companyNameFilter) < 20) set @companyNameFilter += '%'
set @whereClause += 'CompanyName like @companyName '
end
if @ageFilter is not null
begin
if (LEN(@whereClause) <> 0) set @whereClause += ' and '
set @whereClause += 'Age = @age '
end
if @dateFilter is not null
begin
if (LEN(@whereClause) <> 0) set @whereClause += ' and '
set @whereClause += 'StartDate = @startDate '
end
set @sql = 'select FirstName, LastName, CompanyName, Age, StartDate
from People'
if (LEN(@whereClause) <> 0) set @sql += ' where ' + @whereClause
set @params = '@lastName varchar(20),
@companyName varchar(20),
@age int,
@startDate datetime'
execute sp_executesql @sql, @params,
@lastName = @lastNameFilter,
@companyName = @companyNameFilter,
@age = @ageFilter,
@startDate = @dateFilter
end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
除了众所周知的硬编码值之外,您永远不会将任何内容连接到要发送到数据库引擎的 SQL 语句中,因此它对于所有当前已知的 SQL 注入方法都是安全的(并且应该能够抵御未来的攻击)。但是,它确实存在其他问题(例如未声明@startDate)。
You never concatenate anything besides well-known, hard-coded values into a SQL statement to be issued to the database engine, so it is safe from all currently known SQL injection approaches (and should be robust against future attacks). It does, however, have other problems (like @startDate not being declared).
是的,您对字符串 concat 和 sp_executesql 的使用是正确的,并且 SQL 注入不会成为问题。
不,仅仅因为 LINQ 是新热门并不意味着它是正确的解决方案。
也就是说,您的 varchar(20) 参数很容易溢出,您可能需要将它们稍微增加一点,至少达到实际字段的大小。
Yes, your use of string concat and sp_executesql is correct and SQL injections won't be an issue.
And no, just because LINQ is the new hotness doesn't mean it is the right solution.
That said, your varchar(20) parameters can easily overflow, you may want to bump those up a bit, to at least the size of the actual field.
您不需要动态 SQL 来创建可选的 WHERE 子句...只需使用:
也应该更快,并且没有字符串溢出、注入等风险。
像这样:
You don't need dynamic SQL to make optional WHERE clauses... just use:
Should be faster also, and no risk for overflowing strings, injection, or whatever.
Like this:
即使是……“呃”。
为什么不使用临时表,用与非可选参数匹配的元素结果的 ID 填充它,然后根据已指定的参数从临时表中消除其余内容?完成后,只需加入您要查找的结果集即可。
Even if it is... "ugh".
Why not instead use a temp table, populate it with the IDs of the element results that match your non-optional parameters and then eliminate the rest from the temp table based on the parameters that have been specified? Once you've done that just join on the result set you're looking for.
我认为是这样。至少,它看起来还不错。但这可能不是我会采取的方式。
安全性的关键之一是永远永远永远永远编写自己的安全代码。您总是希望尽可能多地依赖平台提供的和内置的机制。您通过使用
sp_executesql
来做到这一点,但我希望您还可以做更多的事情。根据要求,我可能会这样做:
不需要动态 sql,并且 WHERE 子句中没有“OR”。
I think so. At least, it looks okay. But it's probably not how I'd go about it.
One of the key tenants of security is never never never ever write your own security code. You always want to lean as much as possible on the mechanisms provided by and built into your platform. You're doing that somewhat via your use of
sp_executesql
, but I expect you could do more as well.By request, I'd probably do it more like this:
No dynamic sql needed, and no "OR"s in the WHERE clause.
为什么要在存储过程中这样做?更好的解决方案可能是在客户端攻击此问题,在调用存储过程之前转义字符串并检查长度。 MS Enterprise DAAB (.NET) 等库提供了便捷的方法,通过在将参数添加到命令对象时指定参数的数据类型和长度来实现此目的。
Why do this in the stored procedure? A better solution might be to attack this on the client side, escaping strings and checking lengths before calling the stored proc. Libraries like the MS Enterprise DAAB (.NET) provide convenient ways to do this by specifying datatype and length of parameters when you add them to the command object.
差不多了。
防止 SQL 注入的关键是通过“批准”机制正确处理参数并避免字符串连接。
您的代码不会使用参数构建字符串:它们通过 sp_executesql 进行分离和清理。
你是否会这样做是另一回事......正如其他答案所示
Pretty much.
The key to preventing SQL injection is correct handling of parameters via an "approved" mechanism and avoiding string concatenation.
Your code does not build up a string with the parameters: they are separated and cleaned via sp_executesql.
Whether you'd do it this way is a different matter... as other answers show