設定基于Column - Level 的VPD
從Oracle 10g開始,我們可以設定基于column-level的VPD,進而保護那些資料表中的重要資訊列,比如password column、Price等(這個要根據具體的應用需求來定),有兩種column-level的方法可以使用:
1)使用column-level VPD 保護資料不被通路
2)Display the column with NULL values
說明:1)一個查詢中包含被保護的column
2)和基于row-based VPD有所不同,在column-level VPD中,所有的行均可以被通路,但是被保護列可以被隔離或采用MASK顯示。
3)column-level VPD在表和視圖上均可設定
實作:和row-based VPD相似,我們隻需在調用dbms_rls.add_policy的時候,指定sec_relevant_cols(指定被保護列),sec_relevant_cols_opt(MASK)兩個參數即可.
下面我通過一個test case來簡單的介紹一下
需求說明:
對于study.customer 表中的status 字段,不允許維護帳戶(user_a,user_b)檢視或顯示為NULL。
實作過程
1)建立測試表、使用者,并授予相應的權限
--建表
create table study.customer
(region varchar2(4),
msisdn varchar2(11),
status varchar2(2)
);
--插入資料
insert into study.customer values('530','13905301234','0');
insert into study.customer values('530','13905305678','1');
insert into study.customer values('531','13805318888','0');
insert into study.customer values('531','13605319999','1');
insert into study.customer values('532','15805320000','0');
insert into study.customer values('533','15905336666','0');
commit;
--授權
create user user_a identified by user_a default tablespace data_01;
create user user_b identified by user_b default tablespace data_01;
grant create session to user_a,user_b;
grant select,insert,update,delete on study.customer to user_a,user_b;
grant execute on dbms_rls to user_a,user_b;
2)建立一個security package,并授權
create or replace package study.security_pkg as
function test_security(owner varchar2,objname varchar2) return varchar2;
end;
/
create or replace package body study.security_pkg is
function test_security(owner varchar2,objname varchar2) return varchar2 is
v_sql varchar2(2000):='1=0';
begin
if (sys_context('USERENV','SESSION_USER') ='STUDY') then
v_sql:=null;
end if;
return v_sql;
end;
end;
/
grant execute on study.security_pkg to public;
create or replace public synonym security_pkg for study.security_pkg;
3)設定policy
begin
dbms_rls.add_policy(
object_schema => 'STUDY',
object_name => 'CUSTOMER',
policy_name => 'C_COL_POLICY',
function_schema => 'STUDY',
policy_function => 'SECURITY_PKG.TEST_SECURITY',
sec_relevant_cols => 'STATUS');
end;
/
--在這個security policy 設定中,我們指定了status列是被保護的列,所有的維護帳戶不能通路該列,否則将傳回0行。
4)測試column-level VPD
下面我們來感受一下吧(user_a,user_b是受限的維護帳戶,看看效果)
SQL> conn user_a/user_a
已連接配接。
SQL> select * from study.customer;
未標明行
SQL> select region,msisdn from study.customer;
REGI MSISDN
---- -----------
530 13905301234
530 13905305678
531 13805318888
531 13605319999
532 15805320000
533 15905336666
已選擇6行。
SQL> select msisdn,status from study.customer;
未標明行
SQL> conn user_b/user_b
已連接配接。
SQL> select * from study.customer;
未標明行
SQL> select region,msisdn from study.customer;
REGI MSISDN
---- -----------
530 13905301234
530 13905305678
531 13805318888
531 13605319999
532 15805320000
533 15905336666
已選擇6行。
SQL> select msisdn,status from study.customer;
未標明行
SQL> conn study/study
已連接配接。
SQL> select * from study.customer;
REGI MSISDN ST
---- ----------- --
530 13905301234 0
530 13905305678 1
531 13805318888 0
531 13605319999 1
532 15805320000 0
533 15905336666 0
已選擇6行。
SQL> select msisdn,status from study.customer;
MSISDN ST
----------- --
13905301234 0
13905305678 1
13805318888 0
13605319999 1
15805320000 0
15905336666 0
已選擇6行。
SQL>
5)補充說明
一、如果要保護多列,我們隻需要在sec_relevant_cols參數中指定多個列即可(用,分開),比如
begin
dbms_rls.add_policy(
object_schema => 'STUDY',
object_name => 'CUSTOMER',
policy_name => 'C_COL_POLICY',
function_schema => 'STUDY',
policy_function => 'SECURITY_PKG.TEST_SECURITY',
sec_relevant_cols => 'MSISDN,STATUS');
end;
/
二、如果要采用masking option,我們隻需要在設定policy的時候,指定sec_relevant_cols_opt 參數為DBMS_RLS.ALL_ROWS即可,比如:
begin
dbms_rls.add_policy(
object_schema => 'STUDY',
object_name => 'CUSTOMER',
policy_name => 'C_COL_POLICY',
function_schema => 'STUDY',
policy_function => 'SECURITY_PKG.TEST_SECURITY',
sec_relevant_cols => 'STATUS',
sec_relevant_cols_opt => dbms_rls.all_rows);
end;
/
在這種保護模式下,被保護的列,均顯示是NULL。
三、同樣的如果我們需要保護涉及到該列的DML操作時,需要設定如下2個參數(前面的row-based VPD中已經介紹過了)
begin
dbms_rls.add_policy(
object_schema => 'STUDY',
object_name => 'CUSTOMER',
policy_name => 'C_COL_POLICY',
function_schema => 'STUDY',
policy_function => 'SECURITY_PKG.TEST_SECURITY',
statement_types => 'SELECT,INSERT,UPDATE,DELETE',
update_check => TRUE,
sec_relevant_cols => 'STATUS');
end;
/
四、masking option隻支援查詢操作,對DML操作無效
五、捎帶說一下
如果要删除一個policy,可以通過dbms_rls.drop_policy完成,如
begin
dbms_rls.drop_policy (object_schema =>'STUDY', object_name =>'CUSTOMER', policy_name=> 'C_COL_POLICY');
end;
/
如果要enable/disable一個policy可以通過dbms_rls.enable_policy完成,如
SQL> exec dbms_rls.enable_policy('STUDY','CUSTOMER','C_COL_POLICY',FALSE);
PL/SQL procedure successfully completed
SQL> exec dbms_rls.enable_policy('STUDY','CUSTOMER','C_COL_POLICY',TRUE);
PL/SQL procedure successfully completed
SQL>
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7551038/viewspace-614387/,如需轉載,請注明出處,否則将追究法律責任。