隨著資料敏感度提升與用戶數增加,資料庫層級的列級安全(Row-Level Security)成為關鍵需求。Oracle 虛擬私有資料庫 (VPD),即細粒度存取控制 (FGAC),透過在查詢執行時動態附加述詞,實現無感知的列級資料過濾。
DBA 在資料表上定義安全政策,關聯一個政策函數。當用戶查詢該表時,Oracle 自動呼叫政策函數取回述詞字串(如 WHERE am_name = 'admin'),透明地改寫原始查詢:
-- 原始查詢
SELECT * FROM accounts;
-- VPD 自動改寫
SELECT * FROM accounts WHERE am_name = 'admin';
為平衡安全彈性與查詢效能,10g 引入多種政策類型,依述詞的動態程度分級:
| 政策類型 | 述詞特性 | 重新評估時機 | 適用場景 |
|---|---|---|---|
| DYNAMIC (預設) | 完全動態,每列、每用戶、每次存取皆重新計算 | 每次查詢 | 述詞高度動態,依賴即時計算 |
| CONTEXT_SENSITIVE | 述詞前半段靜態,後半段依應用程式上下文 (App Context) 變數決定 | 僅當應用程式上下文變更時 | Web 應用共用 DB 帳號,透過上下文區分用戶權限 |
| SHARED_CONTEXT_SENSITIVE | 同上,但述詞可跨會話共享快取 | 上下文變更時 | 多用戶共用相同上下文值的場景 |
| STATIC | 述詞完全靜態,僅依資料庫用戶身分決定 | 僅首次執行,結果快取於 SGA 永不重算 | 託管應用,每個資料庫用戶對應固定資料範圍 |
| SHARED_STATIC | 同上,述詞跨會話共享 | 永不重算 | 大量用戶共用相同靜態述詞 |
CREATE OR REPLACE FUNCTION vpd_pol_func (
p_schema IN VARCHAR2, p_table IN VARCHAR2
) RETURN VARCHAR2 IS
BEGIN
RETURN 'balance < sys_context(''vpdctx'', ''maxbal'')';
END;
/
BEGIN
DBMS_RLS.ADD_POLICY (
object_schema => 'scott',
object_name => 'accounts',
policy_name => 'bal_limit_pol',
function_schema => 'scott',
policy_function => 'vpd_pol_func',
policy_type => DBMS_RLS.CONTEXT_SENSITIVE
);
END;
/
會話建立時設定 VPDCTX.MAXBAL,若會話期間未變更,Oracle 直接重用述詞,避免重複執行函數。
CREATE OR REPLACE FUNCTION vpd_pol_func (
p_schema IN VARCHAR2, p_table IN VARCHAR2
) RETURN VARCHAR2 IS
BEGIN
RETURN 'cust_name = sys_context(''vpdctx'', ''cust_name'')';
END;
/
BEGIN
DBMS_RLS.ADD_POLICY (
...
policy_type => DBMS_RLS.STATIC
);
END;
/
登入觸發器設定 VPDCTX.CUST_NAME,述詞永久快取,速度最快。
STATIC 政策為雙面刃:若假設的「上下文不變」在執行期被打破(如中途切換客戶),政策函數不會重跑,導致返回錯誤資料集。除非 100% 確定上下文不可變,否則優先選擇
CONTEXT_SENSITIVE。
CREATE CONTEXT) 並授權封裝設定值DBMS_RLS.ADD_POLICY 的 SEC_RELEVANT_COLS 與 SEC_RELEVANT_COLS_OPT 驗證欄位級遮罩V$VPD_POLICY 確認政策生效狀態