預存程序是資料庫應用的核心邏輯載體。本文探討兩大安全機制:
-- 建立測試表
USE testDb2; GO
CREATE TABLE dbo.tb_demo (id int NOT NULL, submitdate datetime NULL, commment nvarchar(200) NULL); GO
INSERT tb_demo SELECT 1024, GETDATE(), REPLICATE('A',100); WAITFOR DELAY '00:00:04';
INSERT tb_demo SELECT 1024, GETDATE(), REPLICATE('B',50); GO
-- 未加密程序
CREATE PROCEDURE CPP_test_Original AS SELECT * FROM tb_demo; GO
-- 加密程序
CREATE PROCEDURE CPP_test_Encryption WITH ENCRYPTION AS EXEC CPP_test_Original; GO

注意:加密前**務必備份原始碼**;加密僅隱藏定義,程序仍可被 EXECUTE、ALTER、DROP。
預設 EXECUTE AS CALLER 需呼叫者擁有底層物件權限。透過指定執行內容,僅需授與程序執行權限即可。
| 選項 | 說明 |
|---|---|
| CALLER | 預設。呼叫者需同時擁有程序與參考物件權限。 |
| SELF | 等同建立/修改程序的使用者 (儲存於 execute_as_principal_id)。 |
| OWNER | 程式碼以模組擁有者身分執行 (擁有者必須為單一帳號,非角色)。 |
| 'user_name' | 指定資料庫使用者身分執行 (需為單一帳號)。 |
-- 1. 建立刪除程序
CREATE PROCEDURE dbo.CPP_DEL_ALL_Tb_Demo AS DELETE dbo.tb_demo; GO
-- 2. 建立低權限登入/使用者 TonyZhang,僅授 EXEC 權限
USE master; GO
CREATE LOGIN TonyZhang WITH PASSWORD = '123b3b4'; GO
USE testDb2; GO
CREATE USER TonyZhang; GO
GRANT EXEC ON dbo.CPP_DEL_ALL_Tb_Demo TO TonyZhang; GO
-- TonyZhang 執行 → 成功 (DELETE 屬所有權鏈涵蓋範圍)
-- 若改為 TRUNCATE → 失敗 (TRUNCATE 不在所有權鏈內)
-- 3. 建立動態 SQL 程序,需跨資料表查詢
CREATE PROCEDURE dbo.CPP_SEL_CountRowsFromAnyTable @SchemaAndTable nvarchar(255)
AS EXEC ('SELECT COUNT(1) FROM ' + @SchemaAndTable); GO
GRANT EXEC ON dbo.CPP_SEL_CountRowsFromAnyTable TO TonyZhang; GO
-- TonyZhang 執行 → 失敗 (動態 SQL 不走所有權鏈,需目標表 SELECT 權限)
-- 4. 建立高權限帳號 JackWang,授目標表 SELECT
CREATE LOGIN JackWang WITH PASSWORD = '123b3b4'; GO
CREATE USER JackWang; GRANT SELECT ON dbo.tb_demo TO JackWang; GO
-- 5. 修改程序執行內容為 JackWang
ALTER PROCEDURE dbo.CPP_SEL_CountRowsFromAnyTable @SchemaAndTable nvarchar(255)
WITH EXECUTE AS 'JackWang'
AS EXEC ('SELECT COUNT(1) FROM ' + @SchemaAndTable); GO
-- TonyZhang 再次執行 → 成功 (以 JackWang 身分存取 tb_demo)
