虛擬私有資料庫 (VPD),又稱細粒度存取控制 (FGAC),提供列級安全功能。自 Oracle 8i 推出,廣泛應用於教育、金融等領域。VPD 透過在查詢執行時動態附加謂詞,過濾使用者可見資料列。例如:
-- 原始查詢 SELECT * FROM accounts; -- VPD 自動重寫 SELECT * FROM accounts WHERE am_name = 'SCOTT';
DBA 在資料表上定義安全策略,策略函數回傳謂詞字串(如 WHERE am_name = 'SCOTT')。
Oracle 10g 依謂詞動態程度提供五種策略類型,減少重複解析開銷:
每次存取、每列、每使用者皆重新評估策略函數。適用於謂詞高度動態(如依應用程式內容變化)的情境。
謂詞分為靜態部分(如欄位名)與動態部分(如應用程式內容變數)。若會話期間應用程式內容未變,Oracle 10g 可快取謂詞,避免重複執行函數。
-- 策略函數範例
CREATE OR REPLACE FUNCTION vpd_pol_func(p_schema VARCHAR2, p_table VARCHAR2) RETURN VARCHAR2 IS
BEGIN
RETURN 'balance < SYS_CONTEXT(''vpdctx'', ''maxbal'')';
END;
建立策略:
DBMS_RLS.ADD_POLICY(..., policy_type => DBMS_RLS.CONTEXT_SENSITIVE);
謂詞完全由使用者身分決定,會話期間不變。Oracle 在 SGA 快取謂詞,策略函數僅執行一次,效能最佳。但若假設錯誤(如應用程式內容中途變更),將回傳錯誤結果,使用時需極謹慎。
-- 策略函數
CREATE OR REPLACE FUNCTION vpd_pol_func(p_schema VARCHAR2, p_table VARCHAR2) RETURN VARCHAR2 IS
BEGIN
RETURN 'cust_name = SYS_CONTEXT(''vpdctx'', ''cust_name'')';
END;
-- 策略定義
DBMS_RLS.ADD_POLICY(..., policy_type => DBMS_RLS.STATIC);
多張資料表共用同一策略函數且應用程式內容未變時,避免因切換資料表而重複執行函數。
DBMS_RLS.ADD_POLICY(..., policy_type => DBMS_RLS.SHARED_CONTEXT_SENSITIVE);
結合共享與靜態特性,適用於多表共用且謂詞完全固定的情境。
DBMS_RLS.ADD_POLICY(..., policy_type => DBMS_RLS.SHARED_STATIC);
僅當查詢包含特定敏感欄位時才套用 VPD 策略。範例:
ACCTNO ACCT_NAME BALANCE 1 BILL CAMP 1000 2 TOM CONNOPHY 2000 3 ISRAEL D 1500
限制 Michelle 僅能查看餘額 ≤ 1600 的帳戶。執行 SELECT * FROM accounts; 時,帳號 2 被隱藏;SELECT COUNT(*) FROM accounts; 回傳 2 而非 3。
此機制確保聚合函數亦受策略約束,防止資料外洩。