最近在项目中某个功能遇到了阻塞造成的Time out错误。所以需要在执行该功能的时候开启一个线程检测SQL Server中阻塞会话。但是程序本身使用的sql帐号本身不具备VIEW Sever State权限。这个权限是sys_admin角色的。所以就需要使用证书将View Server State权限赋予给普通账号。
在开发之前找到了以下两篇博文参考:
SQL Server 2005: 存储过程签名 - stswordman - 博客园
http://www.cnblogs.com/stswordman/archive/2008/07/29/1255322.html
这一篇使用了master key. 当数据库备份后, 在其他数据库还原时需要master key.
Pitching Pebbles - Using Certificates to Grant Privileges | ColleenMorrow.com
http://colleenmorrow.com/2011/12/19/tossing-pebbles-using-certificates-to-grant-privileges/
这一篇直接使用的证书的密钥做. 没有前一篇master key带来的问题. 只是示例使用的是master库.以及直接赋予的sys_admin角色的权限.
本人结合两篇博文的要点,采用证书密码的方式授予View Server State权限。
以下是代码
新建一个查看阻塞进程的存储过程:
USE [TestDB] GO CREATE PROC [dbo].[sp_CheckBlockSession] AS WITH CTE_SID ( BSID, SID, sql_handle ) AS ( SELECT blocking_session_id , session_id , sql_handle FROM sys.dm_exec_requests WHERE blocking_session_id <> 0 UNION ALL SELECT A.blocking_session_id , A.session_id , A.sql_handle FROM sys.dm_exec_requests A JOIN CTE_SID B ON A.SESSION_ID = B.BSID ) SELECT C.BSID AS blocking_session_id, C.SID AS session_id, S.login_name , S.host_name , S.status , S.cpu_time , S.memory_usage , S.last_request_start_time , S.last_request_end_time , S.logical_reads , S.row_count , q.text FROM CTE_SID C JOIN sys.dm_exec_sessions S ON C.sid = s.session_id CROSS APPLY sys.dm_exec_sql_text(C.sql_handle) Q ORDER BY sid
新建一个最小权限账户
USE TestDB GO --新建一个最小权限账户 CREATE LOGIN TEST_View WITH PASSWORD = '123'; CREATE USER TEST_View FOR LOGIN Test_View --让该账户有权限执行存储过程dbo.sp_CheckBlockSession GRANT EXECUTE ON sp_CheckBlockSession TO Test_View
测试最小权限账户执行sp_CheckBlockSession
EXECUTE AS LOGIN = 'TEST_View' ; EXEC sp_CheckBlockSession REVERT ; --错误消息 消息 297,级别 16,状态 1,过程 sp_CheckBlockSession,第 3 行 用户没有执行此操作的权限。
USE TestDB GO --创建证书以及授权 CREATE CERTIFICATE certSignCheckBlockSession_1 ENCRYPTION BY PASSWORD ='TEST111' WITH SUBJECT = 'for signing procedure sp_CheckBlockSession', EXPIRY_DATE='2025-10-10' ; -- sp_CheckBlockSession ADD SIGNATURE TO sp_CheckBlockSession BY CERTIFICATE certSignCheckBlockSession_1 WITH PASSWORD = 'TEST111' ; BACKUP CERTIFICATE certSignCheckBlockSession_1 TO FILE = 'certSignCheckBlockSession_1.cer' ; USE master GO CREATE CERTIFICATE certSignCheckBlockSession_1 FROM FILE = 'certSignCheckBlockSession_1.cer' ; -- 创建登录并映射到证书 CREATE LOGIN L_TESTVIEW FROM CERTIFICATE certSignCheckBlockSession_1 ; -- 通过授权映射登录的方式将ALTER ANY LOGIN权限赋给证书 GRANT VIEW SERVER STATE TO L_TESTVIEW ;
--测试最小权限账户权限 USE TestDB GO EXECUTE AS LOGIN = 'TEST_View' ; EXEC sp_CheckBlockSession REVERT ;--成功得到结果, 不再提示用户没有此操作权限.
以上是使用证书签名存储过程的全部过程. 可以实现最小粒度权限的赋予。这样在生产环境中,就避免了赋予不必要的管理权限。降低风险!
注意事项:证书备份路径的问题. 如果没有指定绝对路径。则备份文件在D:\Program Files (x86)\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA(楼主的机器)目录下面。这个目录有可能权限不足而无法备份到里面。本来我想使用绝对路径的。但是由于我开发某个项目时,使用了一个功能造成我当前账户的权限被缩小到很小。无法使用绝对路径进行备份,所以才使用了默认路径。各位做测试的话要注意这个问题。