如何使用 sp_executesql 来避免 SQL 注入
How to use sp_executesql to avoid SQL Injection
在下面的示例代码中,Table名称是一个输入参数。在这种情况下,如何避免使用 sp_executesql
注入 SQL。下面是示例代码,我试图使用 sp_executesql
来避免它,但它不起作用。谁能告诉我如何更正它?
ALTER PROC Test @param1 NVARCHAR(50),
@param2 INT,
@tblname NVARCHAR(100)
AS
BEGIN
DECLARE @sql NVARCHAR(1000)
SET @sql= N' select * from ' + @tblname
+ ' where name= @param1 and id= @param2';
PRINT @sql
EXEC Sp_executesql
@sql,
N'@param1 nvarchar(50), @param2 int',
@param1,
@param2;
END
EXEC Test
'John',
2,
' emp; delete from emp where id = 567; select * from emp '
输出:
打印消息:
select * from emp; delete from emp where id = 567; select * from emp where name= @param1 and id= @param2;
所有输入参数完全代入,删除一行。
请让我知道如何处理这种情况。
您可以将 table 名称括在 []
中
SET @sql= N' select * from [' + @tblname + '] where name= @param1 and id= @param2';
但是,如果您使用由两部分组成的命名约定,例如 dbo.tablename
,您必须添加额外的解析,因为 [dbo.tablename]
将导致:
Invalid object name [dbo.tablename].
您应该解析它,使其等于 dbo.[tablename]
。
你可以先检查参数值是否确实是一个table名字:
ALTER PROC Test @param1 NVARCHAR(50),
@param2 INT,
@tblname NVARCHAR(100)
AS
BEGIN
DECLARE @sql NVARCHAR(1000)
IF EXISTS(SELECT 1 FROM sys.objects WHERE type = 'u' AND name = @tblname)
BEGIN
SET @sql= N' select * from ' + @tblname
+ ' where name= @param1 and id= @param2';
PRINT @sql
EXEC Sp_executesql
@sql,
N'@param1 nvarchar(50), @param2 int',
@param1,
@param2;
END
END
如果传递的值不是 table 名称,您的程序将不会执行任何操作;或者您可以将其更改为引发错误。如果参数包含查询,这样你就安全了。
在下面的示例代码中,Table名称是一个输入参数。在这种情况下,如何避免使用 sp_executesql
注入 SQL。下面是示例代码,我试图使用 sp_executesql
来避免它,但它不起作用。谁能告诉我如何更正它?
ALTER PROC Test @param1 NVARCHAR(50),
@param2 INT,
@tblname NVARCHAR(100)
AS
BEGIN
DECLARE @sql NVARCHAR(1000)
SET @sql= N' select * from ' + @tblname
+ ' where name= @param1 and id= @param2';
PRINT @sql
EXEC Sp_executesql
@sql,
N'@param1 nvarchar(50), @param2 int',
@param1,
@param2;
END
EXEC Test
'John',
2,
' emp; delete from emp where id = 567; select * from emp '
输出: 打印消息:
select * from emp; delete from emp where id = 567; select * from emp where name= @param1 and id= @param2;
所有输入参数完全代入,删除一行。 请让我知道如何处理这种情况。
您可以将 table 名称括在 []
SET @sql= N' select * from [' + @tblname + '] where name= @param1 and id= @param2';
但是,如果您使用由两部分组成的命名约定,例如 dbo.tablename
,您必须添加额外的解析,因为 [dbo.tablename]
将导致:
Invalid object name [dbo.tablename].
您应该解析它,使其等于 dbo.[tablename]
。
你可以先检查参数值是否确实是一个table名字:
ALTER PROC Test @param1 NVARCHAR(50),
@param2 INT,
@tblname NVARCHAR(100)
AS
BEGIN
DECLARE @sql NVARCHAR(1000)
IF EXISTS(SELECT 1 FROM sys.objects WHERE type = 'u' AND name = @tblname)
BEGIN
SET @sql= N' select * from ' + @tblname
+ ' where name= @param1 and id= @param2';
PRINT @sql
EXEC Sp_executesql
@sql,
N'@param1 nvarchar(50), @param2 int',
@param1,
@param2;
END
END
如果传递的值不是 table 名称,您的程序将不会执行任何操作;或者您可以将其更改为引发错误。如果参数包含查询,这样你就安全了。