VPD = 細粒度訪問控制 (FGAC) = 行級安全 (RLS)。通過在查詢重寫階段透明附加謂詞,實現「同一張表,不同用戶見不同行」,無需修改應用 SQL。
'dept_id = 10')。DBMS_RLS.ADD_POLICY 綁定表、函數、策略類型。SYS_CONTEXT('namespace','attr') 實現動態變量注入。| 類型 | 重新求值頻率 | 適用場景 | 性能 |
|---|---|---|---|
| DYNAMIC (默認) | 每行、每次查詢 | 謂詞高度動態(如基於行級業務規則) | 最低 |
| CONTEXT_SENSITIVE | 會話上下文變化時 | 謂詞依賴 SYS_CONTEXT,會話內相對穩定 | 高 |
| SHARED_CONTEXT_SENSITIVE | 跨會話共享上下文變化時 | 多會話共享同一上下文屬性(如多租戶 SaaS) | 更高 |
| STATIC | 僅首次載入 (SGA 緩存) | 謂詞完全由登錄用戶決定,會話內永不變 | 最高 |
| SHARED_STATIC | 跨會話共享 SGA 緩存 | 多用戶共享相同謂詞(如報表固定過濾) | 極高 |
CREATE OR REPLACE FUNCTION vpd_dynamic (
p_schema VARCHAR2, p_obj VARCHAR2
) RETURN VARCHAR2 IS
BEGIN
RETURN 'am_name = ''' || SYS_CONTEXT('USERENV','SESSION_USER') || '''';
END;
/
BEGIN
DBMS_RLS.ADD_POLICY(
object_schema => 'SCOTT',
object_name => 'ACCOUNTS',
policy_name => 'DYN_ACCT',
function_schema => 'SEC_ADMIN',
policy_function => 'VPD_DYNAMIC',
policy_type => DBMS_RLS.DYNAMIC
);
END;
/
CREATE OR REPLACE FUNCTION vpd_ctx_sens (
p_schema VARCHAR2, p_obj VARCHAR2
) RETURN VARCHAR2 IS
BEGIN
RETURN 'balance < ' || SYS_CONTEXT('VPDCTX','MAXBAL');
END;
/
BEGIN
DBMS_RLS.ADD_POLICY(
policy_name => 'CTX_BAL',
policy_type => DBMS_RLS.CONTEXT_SENSITIVE, -- 關鍵差異
...
);
END;
/
應用登錄後設置上下文:
CREATE OR REPLACE CONTEXT VPDCTX USING pkg_vpd_ctx;
-- 登錄觸發器中
DBMS_SESSION.SET_CONTEXT('VPDCTX','MAXBAL', 100000);
CREATE OR REPLACE FUNCTION vpd_static (...) RETURN VARCHAR2 IS
BEGIN
RETURN 'cust_name = ' || SYS_CONTEXT('VPDCTX','CUST_NAME');
END;
/
BEGIN
DBMS_RLS.ADD_POLICY(
policy_type => DBMS_RLS.STATIC, -- 只求值一次,SGA緩存
...
);
END;
/
⚠️ 風險:若會話中 CUST_NAME 變更,謂詞不會刷新 → 返回錯誤數據!
僅當「用戶登錄後謂詞終身不變」時使用(如多租戶固定租戶 ID)。
CONTEXT_SENSITIVE。STATIC。SHARED_* 類型。balance 列)。配合 DBMS_REDACT 可在 VPD 之上再做列級掩碼(如信用卡號只顯示後四位),實現「行級過濾 + 列級掩碼」雙層防護。