oracle Policy的應用--DBMS_RLS.ADD_POLICY
本文通過以下兩篇文章整理所得:
http://www.knowsky.com/386463.html
http://www.itpub.net/thread-1004775-1-1.html
1 前言
資料訪問許可權控制,是一個古老而又實際的問題。
在大部份系統中,許可權控制主要定義為模組進入許可權的控制和資料列訪問許可權的控制(如:某某人可以進入某個控制,倉庫不充許檢視有關金額的欄位等等)。
但在某些系統中,許可權控制又必須定義到資料行訪問許可權的控制,此需求一般出現在同一系統,不同的相對獨立機構使用的情況。(如:集團下屬多個子公司,所有子公司使用同一套資料表,但不同子公司的資料相對隔離)
當然,絕大多數人會選擇在View加上Where子句來進行資料隔離。此方法編碼工作量大、系統適應使用者治理體系的彈性空間較小,一旦許可權邏輯發生變動,就可能需要修改許可權體系,導致所有的View都必須修改。
Policy基本引數/建立語法
begin
-- Call the procedure
sys.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;
參考文件:
Procedure Purpose
object_schema
Schema containing the table, view, or synonym. If no object_schema is specified, the current log-on user schema is assumed.
object_name
Name of table, view, or synonym to which the policy is added.
policy_name
Name of policy to be added. It must be unique for the same table or view.
function_schema
Schema of the policy function (current default schema, if NULL).
policy_function
Name of a function which generates a predicate for the policy. If the function is defined within a package, then the name of the package must be present.
statement_types
Statement types to which the policy applies. It can be any combination of INDEX, SELECT, INSERT, UPDATE, or DELETE. The default is to apply to all of these types except INDEX.
update_check
Optional argument for INSERT or UPDATE statement types. The default is FALSE. Settingupdate_check toTRUE causes the server to also check the policy against the value after insert or update.
enable
Indicates if the policy is enabled when it is added. The default is TRUE.
static_policy
The default is FALSE. If it is set to TRUE, the server assumes that the policy function for the static policy produces the same predicate string for anyone accessing the object, except forSYS or the privilege user who has theEXEMPTACCESSPOLICY privilege.
policy_type
Default is NULL, which means policy_type is decided by the value of static_policy. The available policy types are listed inTable 89-4. Specifying any of these policy types overrides the value of static_policy.
long_predicate
Default is FALSE, which means the policy function can return a predicate with a length of up to 4000 bytes.TRUE means the predicate text string length can be up to 32K bytes.Policies existing prior to the availability of this parameter retain a 32K limit.
sec_relevant_cols
Enables column-level Virtual Private Database (VPD), which enforces security policies when a column containing sensitive information is referenced in a query. Applies to tables and views, but not to synonyms. Specify a list of comma- or space-separated valid column names of the policy-protected object. The policy is enforced only if a specified column is referenced (or, for an abstract datatype column, its attributes are referenced) in the user SQL statement or its underlying view definition. Default is all the user-defined columns for the object.
sec_relevant_cols_opt
Use with sec_relevant_cols to display all rows for column-level VPD filtered queries (SELECT only), but where sensitive columns appear asNULL. Default is set toNULL, which allows the filtering defined withsec_relevant_cols to take effect. Set todbms_rls.ALL_ROWS to display all rows, but with sensitive column values, which are filtered bysec_relevant_cols, displayed asNULL. See"Usage Notes" for restrictions and additional information about this option.
刪除Policy
begin
-- Call the procedure
sys.dbms_rls.drop_policy(object_schema => :要刪除的Policy所在的Schema,
object_name => :要刪除Policy的資料表(或檢視)名稱,
policy_name => :要刪除的Policy名稱);
end;
例子1:
在一家公司,員工只可以看到本部門員工的記錄:
建立表
create table employee(
select 'qi' name,1 deptno,2000 salary from dual
union all select 'guang',2,1600 from dual
union all select 'wang',1,1800 from dual
union all select 'li',1,2200 from dual
union all select 'zhang',2,3000 from dual
);
建立函式
create or replace function FN(p_owner in varchar2,p_object in varchar2) return varchar2 is
begin
return 'deptno=1';
end FN;
建立策略
begin
dbms_rls.add_policy(object_schema => 'dbown'
,object_name => 'employee'
,policy_name => 'salary'
,function_schema => 'dbown'
,policy_function => 'FN'
,sec_relevant_cols => 'salary');
end;
登入dbown使用者檢視employeeb表
select * from employee;
name deptno salary
qi 1 2000
wang 1 1800
li 1 2200
只可以看到部門1的相關記錄。(其他使用者可以看到所有資訊,因為只對dbown使用者做了策略。)
例子2:
在一家公司,員工可以看到本部門的所有資訊,也可以看到其他部門的有關記錄,但對於工資這個敏感資料則不能看到:
根據例子1,只要修改策略即可(表和函式都是巖用例子1的)
begin
dbms_rls.add_policy(object_schema => 'dbown'
,object_name => 'employee'
,policy_name => 'salary'
,function_schema => 'dbown'
,policy_function => 'FN'
,sec_relevant_cols => 'salary'
,sec_relevant_cols_opt => dbms_rls.ALL_ROWS);
end;
登入dbown使用者檢視employeeb表
select * from employee;
name deptno salary
qi 1 2000
guang 2
wang 1 1800
li 1 2200
zhang 2
則所有記錄都有顯示,只是非部門1的記錄不能看到salary.