日期:2014-05-18  浏览次数:20722 次

网上许多文章都说存储过程能防止SQL注入的恶意攻击,确实有效吗?
和SQL语句比起来,安全度可以提高多少啊?

------解决方案--------------------
在调用存储过程的时候,传入的参数在最后被执行的SQL语句中会被数据库服务器软件进行处理,这样就能防止所谓的“SQL注入”。

下面是个例子,比较了两种方法:

要执行的SQL语句:select * from Users where UserName = 'ABCDE'

一、使用字符串拼接产生的SQL语句
string sql = "select * from Users where UserName = '" + userName + "'";

二、存储过程
create procedure GetUserInfoByUserName
(
nvarchar(50) @UserName
)
AS

select * from Users where UserName = @UserName

一般情况下,用户只会在界面上输入符合规则的用户名,但是恶意攻击者可能会尝试输入类似下面这些经过精心准备的用户名:
"'; select * from master.dbo.sysdatabases; --"
"'; exec master.dbo.xp_cmdshell 'dir c:\ > c:\filelist.txt'; --"

如果用第一种方法,最后的SQL就会变成:
select * from Users where UserName = ''; select * from master.dbo.sysdatabases; --'
select * from Users where UserName = ''; exec master.dbo.xp_cmdshell 'dir c:\ > c:\filelist.txt'; --'
你仔细分析一下最后的执行结果。

而使用存储过程,这些字符串最后都会被当成字符串参数参与到最后的SQL查询中,数据库服务器把最后的SQL理解成:查询UserName字段的值为'; select * from master.dbo.sysdatabases; --的数据,不可能找得到。这样不论是攻击者输入什么参数都不会改变设计者编写的SQL语句的语义,也就防止了SQL注入。

使用存储过程不仅仅是能防止SQL注入(当然,在存储过程里面拼接字符串并使用sp_executesql来执行的不算),主要是存储过程是预编译的,对复杂的SQL语句,效率有很大程度上的提升,还可以进一步减少查询时客户端发送到服务端的数据包的大小。其他的好处还有很多,到Google上搜搜看。