/*-----------------------------------------------------------------
採用oracle的dbms_rls包實現數據訪問控制
在大部份系統中,權限控制主要定義為模塊進入權限的控制和數據列訪問權限的控制(如:某某人可以進入某個控制,
倉庫不充許查看有關部門的字段等等)。但在某些系統中,權限控制又必須定義到數據行訪問權限的控制,
此需求一般出現在同一系統,不同的相對獨立機構使用的情況。(如:集團下屬多個子公司,所有子公司使用同一套數據表,
但不同子公司的數據相對隔離), 絕大多數人會選擇在View加上Where子句來進行數據隔離。此方法編碼工作量大、
系統適應用戶管理體系的彈性空間較小,一旦權限邏輯發生變動,就可能需要修改權限體系,導致所有的View都必須修改。
本文探討的使用Oracle提供的Policy管理方法來實現數據行的隔離
注意:這裡的policy是在9i上測試,8i的policy是不同9i的,但是原理是一樣的.
------------------------------------------------------------------*/
-- (1)建立測試數據表(t_policy):
create table t_policy
(
t1 varchar2(10),
t2 number(10)
);
insert into t_policy values('a',10);
insert into t_policy values('b',20);
insert into t_policy values('c',30);
commit;
-- (2)建立測試policy的函數:
create or replace function fn_getpolicy(p_schema in varchar2,p_object in varchar2) return varchar2 is
result varchar2(1000);
begin
result:='t2 not in (10)'; -- 此子句將被加載於啟用了該Policy的DML語言之後
return(result);
end fn_getpolicy;
-- (3)加入policy:
declare
begin
dbms_rls.add_policy(
object_schema =>'APPS', --數據表(或視圖)所在的schema名稱
object_name =>'T_POLICY', --數據表(或視圖)的名稱
policy_name =>'t_testpolicy', --policy的名稱,主要用於將來對policy的管理
function_schema =>'APPS', --返回where子句的函數所在schema名稱
policy_function =>'fn_getpolicy', --返回where子句的函數名稱
statement_types =>'select,insert,update,delete', --要使用該policy的dml類型,如'select,insert,update,delete'
update_check =>true, --僅適用於statement_type為'insert,update',值為'true'或'false'
enable =>true --是否啟用,值為'true'或'false'
);
end;
--註:如果update_check設為'true',則用戶插入的值不符合policy_function返回條件時,該dml執行返回錯誤信息。
-- 現在就可以工作了:
select * from t_policy;
--看看結果怎樣, 是不是少了t2=10這項了.
-- (4)刪除policy
declare
begin
dbms_rls.drop_policy('niegc','t_policy','t_testpolicy');
end;
-- (5)設置policy的狀態
declare
begin
dbms_rls.enable_policy('niegc','t_policy','t_testpolicy',false);
end;
再附上一段,查詢SO時,智能看到自己Sales Order的Policy:
create or replace function ssak.db_data_policy(p_schema in varchar2,p_object in varchar2) return varchar2 is
x_result varchar2(1000);
x_user_id number;
begin
x_user_id:=apps.fnd_global.user_id();
if p_object='OE_ORDER_HEADERS_V' then
x_result:='created_by=' || x_user_id;
else
x_result:=null;
end if;
-- 此子句將加載於啟用了該Policy的DML語言之後
return(x_result);
end db_data_policy;
阅读(1395) | 评论(0) | 转发(0) |