前言
我们在设置数据库存储过程时经常会用到加密,如果遇到版本更新需要修改存储过程时,如果设计数据库时的存储过程没有留存,所以就必须用到存储过程的解密了,原来自己有个解密存储过程在SQL2000下应用无问题,后来升级到SQL2008后不好用了,下在我们就介绍一下在SQL2008下存储过程的解密方法。
存储过程的加密
存储过程加密的方法非常简单,我们在设计存储过程时加下WITH ENCRYPTION就可以了。
这样在数据库里找到存储过程右键点击存储过程时,修改按钮就是灰色的了,无法查看
接下来我们就来讲讲SQL2008存储过程的解密
存储过程的解密
核心过程sp_DecryptObject
我们解密用到的就是一个名为sp_DecryptObject的存储过程,这个存储过程我会在最少贴出其代码。这里我先讲一个怎么使用这个解密的方法。
创建解密存储过程
1.首先打开Microsoft SQL SERVER Managenment Studio,并登陆进去
2.然后打开解密的存储过程,打开后按执行键我们就在master库存创建了一个名为sp_DecryptObject的存储过程。
注:上面的存储过程里面有两个参数,第一个参数就是我们要解密的存储过程名称,第二个参数是要解密的字符长度,默认是4000。
使用创建的存储过程解密
1.首先要新建一个数据库引擎查询。点击文件---新建---数据库引擎查询。
然后在服务器名称这里把我们的服务器名称前面加上admin:
然后上面下拉框选择我们存储过程所在的数据库,在文本编辑器里面输入
sp_DecryptObject 存储过程名,再按执行键,可以看到下方结果页面显示出来我们的存储过程文本了。
sp_Decrypttion参数说明
向上面刚才我们的存储过程这样执行完从文本里面拷贝出来进行修改即可以,但是我们再用一个比较长的存储过程看一下效果
可以看到上面的存储过程文本并没有全部显示出来,这就是因为我们创建存储过程时第二个参数默认为4000的问题
下面我们重新修改一下调用的存储过程,把第二个参数也输入一个大点的值
看看效果
我们把第二个参数加入了一个50000的值,可以看到执行的结果里面所有的存储过程代码全部显示出来了。
sp_Decryption源码
Use master Go if object_ID('[sp_DecryptObject]') is not null Drop Procedure [sp_DecryptObject] Go create procedure sp_DecryptObject ( @Object sysname, --要解密的对象名:函数,存储过程,视图或触发器 @MaxLength int=4000 --评估内容的长度 ) as set nocount on /* 1. 解密 */ if not exists(select 1 from sys.objects a where a.object_id=object_id(@Object) And a.type in('P','V','TR','FN','IF','TF')) begin --SQL Server 2008 raiserror 50001 N'无效的对象!要解密的对象必须是函数,存储过程,视图或触发器。' --SQL Server 2012 --throw 50001, N'无效的对象!要解密的对象必须是函数,存储过程,视图或触发器。',1 return end if exists(select 1 from sys.sql_modules a where a.object_id=object_id(@Object) and a.definition is not null) begin --SQL Server 2008 raiserror 50001 N'对象没有加密!' --SQL Server 2012 --throw 50001, N'无效的对象!要解密的对象必须是函数,存储过程,视图或触发器。',1 return end declare @sql nvarchar(max) --解密出来的SQL语句 ,@imageval nvarchar(max) --加密字符串 ,@tmpStr nvarchar(max) --临时SQL语句 ,@tmpStr_imageval nvarchar(max) --临时SQL语句(加密后) ,@type char(2) --对象类型('P','V','TR','FN','IF','TF') ,@objectID int --对象ID ,@i int --While循环使用 ,@Oject1 nvarchar(1000) set @objectID=object_id(@Object) set @type=(select a.type from sys.objects a where a.object_id=@objectID) declare @Space4000 nchar(4000) set @Space4000=replicate('-',4000) /* @tmpStr 会构造下面的SQL语句 ------------------------------------------------------------------------------- alter trigger Tr_Name on Table_Name with encryption for update as return /**/ alter proc Proc_Name with encryption as select 1 as col /**/ alter view View_Name with encryption as select 1 as col /**/ alter function Fn_Name() returns int with encryption as begin return(0) end/**/ */ set @Oject1=quotename(object_schema_name(@objectID)) '.' quotename(@Object) set @tmpStr= case when @type ='P ' then N'Alter Procedure ' @Oject1 ' with encryption as select 1 as column1 ' when @type ='V ' then N'Alter View ' @Oject1 ' with encryption as select 1 as column1 ' when @type ='FN' then N'Alter Function ' @Oject1 '() returns int with encryption as begin return(0) end ' when @type ='IF' then N'Alter Function ' @Oject1 '() returns table with encryption as return(Select a.name from sys.types a) ' when @type ='TF' then N'Alter Function ' @Oject1 '() returns @t table(name nvarchar(50)) with encryption as begin return end ' else 'Alter Trigger ' @Oject1 'on ' quotename(object_schema_name(@objectID)) '.' (select Top(1) quotename(object_name(parent_id)) from sys.triggers a where a.object_id=@objectID) ' with encryption for update as return ' end set @tmpStr=@tmpStr '/*' @Space4000 set @i=0 while @i < (ceiling(@MaxLength*1.0/4000)-1) begin set @tmpStr=@tmpStr @Space4000 Set @i=@i 1 end set @tmpStr=@tmpStr '*/' ------------ set @imageval =(select top(1) a.imageval from sys.sysobjvalues a where a.objid=@objectID and a.valclass=1) begin tran exec(@tmpStr) set @tmpStr_imageval =(select top(1) a.imageval from sys.sysobjvalues a where a.objid=@objectID and a.valclass=1) rollback tran ------------- set @tmpStr=stuff(@tmpStr,1,5,'create') set @sql='' set @i=1 while @i<= (datalength(@imageval)/2) begin set @sql=@sql isnull(nchar(unicode(substring(@tmpStr,@i,1)) ^ unicode(substring(@tmpStr_imageval,@i,1))^unicode(substring(@imageval,@i,1)) ),'') Set @i =1 end /* 2. 列印 */ declare @patindex int while @sql>'' begin set @patindex=patindex('%' char(13) char(10) '%',@sql) if @patindex >0 begin print substring(@sql,1,@patindex-1) set @sql=stuff(@sql,1,@patindex 1,'') end else begin set @patindex=patindex('%' char(13) '%',@sql) if @patindex >0 begin print substring(@sql,1,@patindex-1) set @sql=stuff(@sql,1,@patindex,'') end else begin set @patindex=patindex('%' char(10) '%',@sql) if @patindex >0 begin print substring(@sql,1,@patindex-1) set @sql=stuff(@sql,1,@patindex,'') end else begin print @sql set @sql='' end end end end Go exec sp_ms_marksystemobject 'sp_DecryptObject' --标识为系统对象 go