Oracle Policy的簡單說明:
Policy應用於數據行訪問權限控制時,其作用簡而言之,就是在查詢數據表時,自動在查詢結果上加上一個Where子句。假如該查詢已有where子句,則在該Where子句后面加上"And ..."。
由Oracle Policy自動加入的Where子句的內容,通常由一個函數來實現。而進行數據行訪問權限控制算法實現的結果,也是通過該函數返回。
Oracle Policy語法說明:
創建策略:
begin
-- Call the procedure
dbms_rls.add_policy(object_schema => :數據表(或視圖)所在的Schema名稱/用戶,
object_name => :數據表(或視圖)的名稱,
policy_name => :policy的名稱
function_schema => :返回Where子句的函數所在Schema名稱/用戶,
policy_function => :返回Where子句的函數名稱,
statement_types => :要使用該Policy的DML類型,如'Select,Insert,Update,Delete',
update_check => 僅適用於Statement_Type為'Insert,Update',值為'True'或'False',
enable => 是否啟用,值為'True'或'False',
static_policy => 默認值為FALSE。如果它被設置為TRUE則所有用戶啟用該策略,sys或特權用戶例外。
policy_type => :默認值是null,意味着static_policy的值決定,在這里指定任何策略將覆蓋static_policy的值。
long_predicate => long_predicate,
sec_relevant_cols => :敏感的字段名稱,
sec_relevant_cols_opt => :設置為dbms_rls.ALL_ROWS來顯示所有的行,敏感的列的值為null);
end;
刪除策略:
begin
dbms_rls.drop_policy(
object_schema=>'要刪除的Policy所在的Schema',
object_name=>'要刪除Policy的數據表(或視圖)名稱',
policy_name=>'要刪除的Policy名稱'
);
end;
改變policy狀態:
begin
dbms_rls.enable_policy(
object_schema=>'要改變的Policy所在的Schema',
object_name=>'要改變Policy的數據表(或視圖)名稱',
policy_name=>'要刪除的Policy名稱',
enable=>'默認True,是否啟用,True為啟用策略,False為禁用策略'
);
end;
需要注意,在普通用戶下是沒有dbms_rls的權限,在使用之前需要對其授權
grant execute,debug on dbms_rls to scott;
具體實現:
在創建策略時需要創建策略使用到的函數:
create or replace function FN(p_schema in varchar2 default NULL,
p_object in varchar2 default NULL)
return varchar2 as
begin
return 'deptno=10';
end;
創建一個策略,只能看到部門為10的數據:
begin
dbms_rls.add_policy(
object_schema=>'scott',
object_name=>'emp',
policy_name=>'emp',
function_schema=>'scott',
policy_function=>'FN',
statement_types=>'SELECT'
);
end;
執行結果:
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7782 CLARK MANAGER 7839 1981/6/9 2450.00 10
7934 MILLER CLERK 7782 1982/1/23 1300.00 10
只顯示部門為10的數據。
如果該用戶可以看到自己部門信息,也可以看到其他部門的部分信息,一些敏感字段則不能看到,比如工資。根據上個策略,只增加兩個條件即可,如下:
begin
dbms_rls.add_policy(
object_schema=>'scott',
object_name=>'emp',
policy_name=>'emp',
function_schema=>'scott',
policy_function=>'FN',
statement_types=>'SELECT',
sec_relevant_cols=>'sal',
sec_relevant_cols_opt=>dbms_rls.ALL_ROWS
);
end;
執行結果:
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7369 SMITH CLERK 7902 1980/12/17 20
7499 ALLEN SALESMAN 7698 1981/2/20 300.00 30
7521 WARD SALESMAN 7698 1981/2/22 500.00 30
7566 JONES MANAGER 7839 1981/4/2 20
7654 MARTIN SALESMAN 7698 1981/9/28 1400.00 30
7698 BLAKE MANAGER 7839 1981/5/1 30
7782 CLARK MANAGER 7839 1981/6/9 2450 10
7788 SCOTT ANALYST 7566 1987/4/19 20
7844 TURNER SALESMAN 7698 1981/9/8 0.00 30
7876 ADAMS CLERK 7788 1987/5/23 20
7900 JAMES CLERK 7698 1981/12/3 30
7902 FORD ANALYST 7566 1981/12/3 20
7934 MILLER CLERK 7782 1982/1/23 1300 10
所有記錄全部顯示,只是配置了敏感字段的sal,不是部門為10的數據則顯示為空。
改變策略狀態:
begin
dbms_rls.enable_policy(
object_schema=>'scott',
object_name=>'emp',
policy_name=>'emp',
enable=>true
);
end;
刪除策略:
begin
dbms_rls.drop_policy(
object_schema=>'scott',
object_name=>'emp',
policy_name=>'emp'
);
end;
這樣就可以實現數據的查詢權限控制了。