【原創】演示一個VPD進行資料訪問控制的示例

leonarding發表於2013-06-17

更多精彩內容盡在


1.什麼是VPDVirtual PrivateDatabase 虛擬私有資料庫,聽起來像是一個獨立自主的資料庫,其實在邏輯上是獨立的,物理上就是一個資料庫。原理就是透過指定過濾策略,對使用者的SQL新增謂詞條件,來達到過濾資料的目的。

2.VPD優點:

精細化訪問

對業務透明,不同的客戶發出相同SQL語句,查詢到的結果集不一樣,可以讓不同客戶只看其相關的資料

對使用者透明,使用者感知不到

不對資料本身做任何操作,只在SQL層面進行過濾處理

VPD是資料庫預設自帶的,無需獨立安裝

3.實驗

我們建一張業務表car,有汽車名,汽車數量,汽車價格三個欄位,插入9條記錄,分成高中低三個檔次

LEO1@LEO1>create table car (namevarchar2(20),num number,cost number);

Table created.

LEO1@LEO1>insert into carvalues('toyota',10,30);         高階車

1 row created.

LEO1@LEO1>insert into carvalues('volvo',50,30);

1 row created.

LEO1@LEO1>insert into carvalues('honda',60,30);

1 row created.

LEO1@LEO1>insert into carvalues('biaozhi',70,20);        中級車

1 row created.

LEO1@LEO1>insert into carvalues('xuetielong',80,20);

1 row created.

LEO1@LEO1>insert into car values('polo',90,20);

1 row created.

LEO1@LEO1>insert into carvalues('xiali',20,10);          低階車

1 row created.

LEO1@LEO1>insert into carvalues('jili',30,10);

1 row created.

LEO1@LEO1>insert into carvalues('byd',40,10);

1 row created.

LEO1@LEO1>commit;

Commit complete.

LEO1@LEO1>select * from car;

NAME                        NUM       COST

-------------------- ------------------------------ -------------------- ----------

toyota                       10         30

volvo                        50         30

honda                       60         30

biaozhi                      70         20

xuetielong                   80         20

polo                         90        20

xiali                         20        10

jili                          30        10

byd                         40         10

9 rows selected.

我們的思路:car表上新增過濾策略“filter_name”和“filter_num”,當select語句中有name欄位時觸發“filter_name”策略,當select語句中有num欄位時觸發“filter_num”策略,過濾策略由函式“fun_name”和“fun_num”實現。

建立函式“fun_name

LEO1@LEO1>create or replace functionfun_name (fun_scheme varchar2,fun_object  varchar2)

return varchar2 as fun_cost varchar2(20);

begin

fun_cost:='cost=30';

return(fun_cost);

end fun_name;

/

2    3    4   5    6    7  

Function created.

建立函式“fun_num

LEO1@LEO1>create or replace functionfun_num (fun_scheme varchar2,fun_object varchar2)

return varchar2 as fun_cost varchar2(20);

begin

fun_cost:='cost=10';

return(fun_cost);

end fun_num;

/

2    3    4   5    6    7  

Function created.

新增過濾策略“filter_name

LEO1@LEO1>begin

dbms_rls.add_policy(

object_schema => 'leo1',

object_name => 'car',

policy_name => 'filter_name',

policy_function => 'fun_name',

sec_relevant_cols => 'name');

end;

/

2    3    4   5    6    7   8    9  

PL/SQL procedure successfully completed.

新增過濾策略“filter_num

LEO1@LEO1>begin

dbms_rls.add_policy(

object_schema => 'leo1',

object_name => 'car',

policy_name => 'filter_num',

policy_function => 'fun_num',

sec_relevant_cols => 'num');

end;

/

2    3    4   5    6    7   8    9  

PL/SQL procedure successfully completed.

當我們要查詢汽車名的時候,會觸發filter_name過濾策略,從而呼叫fun_name函式限制where cost=30的記錄顯示

LEO1@LEO1>select name,cost from car;

NAME                       COST

-------------------- ----------

toyota                       30

volvo                        30

honda                       30

當我們要查詢汽車數量的時候,會觸發filter_num過濾策略,從而呼叫fun_num函式限制where cost=10的記錄顯示

LEO1@LEO1>select num,cost from car;

      NUM       COST

---------- ----------

       20         10

       30         10

       40         10

當我們不想使用過濾策略的時候,如何刪除?

使用drop_policy儲存過程來刪除,filter_namefilter_num過濾策略

LEO1@LEO1>execute dbms_rls.drop_policy('leo1','car','filter_name');

PL/SQL procedure successfully completed.

LEO1@LEO1>execute dbms_rls.drop_policy('leo1','car','filter_num');

PL/SQL procedure successfully completed.

LEO1@LEO1>select * from car;

NAME                        NUM       COST

-------------------- ---------- ----------

toyota                       10         30

volvo                        50         30

honda                        60         30

biaozhi                      70         20

xuetielong                   80         20

polo                         90         20

xiali                        20         10

jili                         30         10

byd                         40         10

9 rows selected.

利用VPD隱藏敏感列資訊

我們設計一個新的“filter_num”策略,只顯示cost=10的記錄,隱藏num列的汽車數量

LEO1@LEO1>begin

dbms_rls.add_policy(

object_schema => 'leo1',

object_name => 'car',

policy_name => 'filter_num',

policy_function => 'fun_num',

sec_relevant_cols => 'num',

sec_relevant_cols_opt =>dbms_rls.all_rows);      只顯示相關的行資訊

end;

/

2    3    4   5    6    7   8    9   10  

PL/SQL procedure successfully completed.

LEO1@LEO1>select * from car;

NAME                        NUM       COST

-------------------- ---------- ----------

toyota                                   30

volvo                                    30

honda                                   30

biaozhi                                  20

xuetielong                               20

polo                                    20

xiali                         20        10

jili                          30         10

byd                        40         10

9 rows selected.

小結:VPD是一種行級安全控制,操作簡單無需新增任何元件即可實施。




2013.6.14
北京
&summer
分享技術~
成就夢想
Blog

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26686207/viewspace-764081/,如需轉載,請註明出處,否則將追究法律責任。

相關文章