我們看一個示例:
第一步、創建一個測試存儲過程,用來delete表tb_Demo的所有數據
USE testDb2
GO
CREATE PROCEDURE dbo.[CPP_DEL_ALL_Tb_Demo]
AS
-- Deletes all rows prior to the data feed
DELETE dbo.[tb_Demo]
GO
第二步:創建一個賬號TonyZhang,並賦於該賬號對該存儲過程的exec權限
USE master
GO
CREATE LOGIN TonyZhang WITH PASSWord = '123b3b4'
USE testDb2
GO
CREATE USER TonyZhang
GO
GRANT EXEC ON dbo.[CPP_DEL_ALL_Tb_Demo] to TonyZhang
以該賬號登錄SQL Server,並執行:
EXECUTE dbo.CPP_DEL_ALL_Tb_Demo
/**
(4 row(s) affected)
**/
注意:此時,雖然TonyZhang除了執行存儲過程[CPP_DEL_ALL_Tb_Demo]之外沒有任何其他權限,但仍然執行了存儲過程,並刪除了表記錄。
如果我們修改存儲過程為:
Alter PROCEDURE dbo.[CPP_DEL_ALL_Tb_Demo]
AS
-- Deletes all rows prior to the data feed
truncate table dbo.[tb_Demo]
GO
此時,再以TonyZhang登錄,並執行存儲過程,會提示:
這是因為所有者權鏈只限定在SELECT、INSERT、UPDATE 和 DELETE。而不包括Truncate,換句話說,系統授於的Exec只既定於SELECT、INSERT、UPDATE 和 DELETE
有人可能會問:如果在存儲過程內部調用動態語句,而不是明確的表名,我們如何限定權限呢?
第三步:我們建立一個存儲過程,功能是傳入一個參數表名,查詢該表的記錄數。
CREATE PROCEDURE dbo.[CPP_SEL_CountRowsFromAnyTable]
@SchemaAndTable nvarchar(255)
AS
EXEC ('SELECT COUNT(1) FROM ' + @SchemaAndTable)
GO
授於Tonyzhang 以執行該存儲過程的權限:
GRANT EXEC ON dbo.[CPP_SEL_CountRowsFromAnyTable] to TonyZhang
go
此時,以Tonyzhang登錄,執行存儲過程,會提示:
注意,此時,tonyzhang雖然有執行存儲過程的權限,但是沒有參數表的select權限,所以執行失敗。
第四步:修改存儲過程的上下文
創建一個新賬號jackwang,賦於表tb_Demo的select權限
USE master
GO
CREATE LOGIN JackWang WITH PASSWord = '123b3b4'
USE Testdb2
GO
CREATE USER JackWang
GRANT SELECT ON OBJECT::dbo.[tb_Demo] TO JackWang
GO
/*******
注意:此時,JackWang 可以執行dbo.[tb_Demo的Select
*******/
修改存儲的執行者
USE Testdb2
GO
alter PROCEDURE dbo.[CPP_SEL_CountRowsFromAnyTable]
@SchemaAndTable nvarchar(255)
WITH EXECUTE AS 'JackWang'
AS
EXEC ('SELECT COUNT(1) FROM ' + @SchemaAndTable)
GO
注意:這樣,我們再調用存儲過程[CPP_SEL_CountRowsFromAnyTable]時,會自動以JackWang的身份運行該存儲過程。
此時,我們仍以Tonyzhang登錄,再執行:
小結:
本文通過簡單的兩個示例開始SQL Server代碼的安全之旅,
1、存儲過程的加密,(注意:加密存儲過程前應該備份原始存儲過程,且加密應該在部署到生產環境前完成。)
2、存儲過程的安全上下文。可以通過上下文設置更加嚴格的數據訪問級別。(主要是對SELECT、INSERT、UPDATE 和 DELETE語句的訪問限制)
後續部分將會涉及SQL Server 2008新增的透明加密(TDE)功能。
邀月注:本文版權由邀月和博客園共同所有,轉載請注明出處。
助人等於自助! [email protected]