十多年 SQL Server 實戰經驗讓我成為預存程序的忠實擁護者。在「直寫 SQL」與「預存程序」的選擇上,我毫不猶豫選後者,核心理由有三:
EXECUTE 權限,無法直接 SELECT * 基表,實現行級、列級管控。WITH ENCRYPTION 讓邏輯在目錄檢視中不可讀,防止托管環境或注入攻擊洩露核心業務邏輯。⚠️ 重要提醒:加密前務必備份原始碼,且應在部署生產環境前完成加密。
USE testDb2; GO
CREATE TABLE dbo.tb_demo (
id INT NOT NULL,
submitdate DATETIME NULL,
commment NVARCHAR(200) NULL
);
INSERT tb_demo SELECT 1024, GETDATE(), REPLICATE('A',100);
WAITFOR DELAY '00:00:04';
INSERT tb_demo SELECT 1024, GETDATE(), REPLICATE('B',50);
-- 未加密
CREATE PROCEDURE CPP_test_Original
AS SELECT * FROM tb_demo; GO
-- 加密
CREATE PROCEDURE CPP_test_Encryption
WITH ENCRYPTION
AS EXEC CPP_test_Original; GO
未加密:sp_helptext 或 SSMS 可直接檢視定義。

加密後:定義顯示為 Encrypted,無法還原(雖然第三方工具可破解,但大幅提高門檻)。

注意:加密不防止 EXECUTE、ALTER、DROP 操作,僅隱藏定義文本。
除了加密文本,EXECUTE AS 子句可設定模組執行身分,滿足多層次安全需求。(詳細語法請參考 MSDN)
| 選項 | 行為描述 | 備註 |
|---|---|---|
CALLER | 以呼叫者身分執行(預設)。呼叫者需同時擁有模組與被引用物件權限。 | SQL Server 2005 行為相容 |
SELF | 等同 EXECUTE AS '建立者'。建立者 SID 存於 sys.sql_modules.execute_as_principal_id。 | 佇列預設值 |
OWNER | 以模組目前擁有者身分執行。無指定擁有者則用結構描述擁有者。 | 擁有者必須為單一帳號,不可為角色/群組;DDL/登入觸發器不可用 |
'user_name' | 指定資料庫使用者身分執行。需存在於目前資料庫,且為單一帳號。 | 最靈活,常用於建立專用代理帳號 |
SELECT、INSERT、UPDATE、DELETE。EXEC('...')、sp_executesql)。EXECUTE AS 控制「執行時權限」,兩者互補。TRUNCATE 導致所有權鏈斷裂、動態 SQL 權限失效,以及如何用代理帳號破解。版權聲明:本文版權由邀月與博客園共同所有,轉載請註明出處。助人等於自助!