SQL注入就不用介绍了,网上很多。下面介绍一下防止 SQL注入的方法。
使用 quotename 函数和 sp_executesql
参考如 下表结构:这是一个文档表里面有一些简单的字段信息
CREATE TABLE [dbo] . [DocumentInfo] (
[ID] [int] IDENTITY ( 1, 1) primary key NOT NULL,-- 主键
[Name] [varchar] ( 100) NOT NULL,-- 文档名字
[FunctionID] [int] NOT NULL , -- 功能 ID 外键
[TypeInfo] [nvarchar] ( 2000) NULL— 描述信息
)
我们可能会按,主键 ID,文档的名字,功能 id, 描述信息进行查询 ,这个一看就是拼接 sql语句,如果不用上面的方法很可能造成 sql注入
例如你写的存储过程可能如下:
CREATE proc [dbo] . [Doc_search]
(
@ID int ,
@name varchar ( 10),
@FID int ,
@Info nvarchar ( 20)
)
as
begin
declare @sql varchar ( 300)
set @sql = 'select * from [DocumentInfo] where 1=1'
if @ID <>- 1
set @sql = @sql + ' and ID=' + CAST ( @ID as varchar )
if @name <> ''
set @sql = @sql + ' and name=''' + CAST ( @name as varchar ) + ''''
if @FID <>- 1
set @sql = @sql + ' and [FunctionID]=' + CAST ( @FID as varchar )
if @Info <> ''
set @sql = @sql + ' and [TypeInfo] like ''%' + CAST ( @Info as varchar )+ '%'''
print @sql
end
exec ( @sql )
虽然你用了带参数的存储过程 ,但本质上还是拼接字符串,没有有效的防治 sql注入。现在 分别用 quotename()函数和 sp_executesql。 Quotename()函数不知道用的请自行查找, sp_executesql的用法 见上一篇动态 sql
Quotename改进如下:
alter proc [dbo] . [Doc_search]
(
@ID int ,
@name varchar ( 10),
@FID int ,
@Info nvarchar ( 20)
)
as
begin
declare @sql varchar ( 300)
set @sql = 'select * from [DocumentInfo] where 1=1'
if @ID <>- 1
set @sql = @sql + ' and ID=' + CAST ( @ID as varchar )
if @name <> ''
set @sql = @sql + ' and name=' + QUOTENAME ( @name , '''' )
if @FID <>- 1
set @sql = @sql + ' and [FunctionID]=' + CAST ( @FID as varchar )
if @Info <> ''
set @Info = '%' + @Info + '%' ;
set @sql = @sql + ' and [TypeInfo] like ' + QUOTENAME ( @Info , '''' )
print @sql
end
exec ( @sql )
但这种方法碰到字段是 Int类型的就会失效
所以推荐使用 sp_executesql 改进存储过程如下:
alter proc [dbo] . [Doc_search]
(
@ID int ,
@name varchar ( 10),
@FID int ,
@Info nvarchar ( 20)
)
as
begin
declare @sql nvarchar ( 300)
set @sql = N'select * from [DocumentInfo] where 1=1'
if @ID <>- 1
set @sql = @sql + ' and ID=@ID'
if @name <> ''
set @sql = @sql + ' and name=@name'
if @FID <>- 1
set @sql = @sql + ' and [FunctionID]=@FID'
if @Info <> ''
set @Info = '%' + @Info + '%' ;
set @sql = @sql + ' and [TypeInfo] like @Info'
print @sql
end
exec sp_executesql @sql , N'@ID as int,@name as varchar(10),@FID as int,@Info as nvarchar(20)' , @ID , @Name , @FID , @Info
这样参数化才是真的参数化 注意 like的用法。用 ’’Sql注入第一种 然后再 注入第三种会发现得不到你想要的结果。 sp_executesql 还是 非常有用的 下一篇介绍 用 sp_executesql 怎样实现比较通用的分页存储过程
转自:http://www.cnblogs.com/wzpo/archive/2010/05/13/1734771.html