利用VPD細粒度訪問策略實現行級安全性 Step By Step

post0發表於2007-02-10
利用VPD細粒度訪問策略實現行級安全性 Step By Step[@more@]相關閱讀:
利用Label Security實現行級安全性 Step By Step

Oracle8i以後的版本都提供了VPD(virtual private database 虛擬專用資料庫)這樣一個強大的功能來實現呼聲日益增高的系統安全性要求。

透過設定基於VPD的細粒度訪問策略,我們可以只透過DBA的工作(不需要修改應用,也就是應用透明化)就可以實現使用者只能訪問自己有許可權訪問的資料,當然如果需要更加複雜的許可權控制開發人員的參與還是必不可少的。

下面用一個簡單的例子來實現這樣的功能,在EMP表中的使用者登入資料庫以後只能查詢和更新自己所屬部門的其它員工資料,不是本部門的不會顯示也不允許更新。

1. 我們需要用到3個使用者,一個是擁有EMP表的SCOTT使用者,一個是用於設定VPD策略的KAMUS使用者,另外一個是在EMP表中有記錄的SMITH使用者。
SCOTT使用者可以利用$ORACLE_HOME/rdbms/admin/scott.sql建立。
@?/rdbms/admin/scott.sql
KAMUS使用者需要能夠執行DBMS_RLS包的許可權。
grant execute on dbms_rls to kamus;
SMITH使用者需要能夠讀取並更新EMP表的許可權。
grant select on scott.emp to smith;

2. 首先用KAMUS使用者建立策略許可權表。為方便起見我們直接透過EMP表建立,本策略表中包含了員工姓名和所屬部門編號。為了更加完善策略函式,我們建立完策略表後在表中新增一條記錄,讓SMITH使用者同時屬於20和10這兩個部門。

SQL> create table access_policy as select ename,deptno from scott.emp;

Table created

SQL> select * from access_policy;

ENAME DEPTNO
---------- ------
SMITH 20
ALLEN 30
WARD 30
JONES 20
MARTIN 30
BLAKE 30
CLARK 10
KING 10
TURNER 30
JAMES 30
FORD 20
MILLER 10

12 rows selected

SQL> insert into access_policy values('SMITH',10);

1 row inserted

SQL> commit;

Commit complete

3. KAMUS使用者建立VPD策略需要的函式。

create or replace function get_user_dept_id
(
p_schema in varchar2,
p_table in varchar2
)
return varchar2
as
l_retstr varchar2(2000);
begin
if (p_schema = user) then
l_retstr := null;
else
for user_rec in
(
select deptno
from access_policy
where ename = USER
) loop
l_retstr := l_retstr||','||user_rec.deptno;
end loop;
l_retstr := ltrim(l_retstr,',');
if (l_retstr is null) then
l_retstr := '1=2';
else
l_retstr := 'DEPTNO IN ('||l_retstr||')';
end if;
end if;
return l_retstr;
end;

該函式實現以下功能:
如果使用SCOTT使用者登入,因為表是屬於該使用者的,所以不加任何限制。
如果使用其它使用者登入(SYS使用者不受此限制),那麼根據EMP表中該使用者的所屬部門決定哪些記錄允許該使用者操作,本例中10和20這兩個部門的員工SMITH使用者將都能看見。
如果登入的使用者不在EMP表中,那麼該使用者檢視不到任何資料,比如KAMUS使用者。

注意:
VPD策略函式必須包含兩個引數,本例中是p_schema和p_table,即使這兩個引數在函式中沒有用到,也必須包含。否則在後面檢索EMP表資料的時候將會報:
PLS-00306: 呼叫 'GET_USER_DEPT_ID' 時引數個數或型別錯誤。

我們用SMITH使用者登入資料庫來測試一下這個函式的返回值。
SQL> select kamus.get_user_dept_id('SCOTT','EMP') from dual;

KAMUS.GET_USER_DEPT_ID('SCOTT'
--------------------------------------------------------------------------------
DEPTNO IN (20,10)


也就是說基於VPD的細粒度訪問策略實際上就是在使用者提交一個SQL以後會將策略函式返回值新增到where語句後面,透過這種方式來限制使用者對於表中資料的訪問。

4. 用KAMUS使用者建立VPD策略。

begin
dbms_rls.add_policy (
object_schema => 'SCOTT',
object_name => 'EMP',
policy_name => 'EMP_SEL_POLICY',
function_schema => 'KAMUS',
policy_function => 'GET_USER_DEPT_ID',
statement_types => 'SELECT'
);
end;
/

這是用於select的策略。

begin
dbms_rls.add_policy (
object_schema => 'SCOTT',
object_name => 'EMP',
policy_name => 'EMP_IUD_POLICY',
function_schema => 'KAMUS',
policy_function => 'GET_USER_DEPT_ID',
statement_types => 'INSERT, UPDATE, DELETE',
update_check => TRUE
);
end;
/

這是用於DML的策略。

5. 至此為止我們的VPD方案就已經設定完畢了。下面我們測試一下。

SQL> conn scott/tiger
已連線。
--SCOTT使用者可以選擇出全部的12條記錄
SQL> select count(*) from emp;

COUNT(*)
----------
12

SQL> conn smith/smith
已連線。
--SMITH使用者只能選擇出屬於10,20部門的6條記錄
SQL> select count(*) from scott.emp;

COUNT(*)
----------
6
--更新也只能更新6行記錄
SQL> update scott.emp set sal=sal+100;

已更新6行。
--如果嘗試插入一個其它部門的員工將會報錯
SQL> insert into scott.emp(empno,ename,deptno) values(9999,'VPD',30);
insert into scott.emp(empno,ename,deptno) values(9999,'VPD',30)
*
第 1 行出現錯誤:
ORA-28115: 策略違反檢驗選項
--即使指定了要更新30部門的資料也是一條都無法更新
SQL> update scott.emp set sal=sal+100 where deptno=30;

已更新0行。
--同樣刪除也只能刪除6行資料
SQL> delete scott.emp;

已刪除6行。
'

結論:
透過基於VPD的細粒度訪問策略可以很簡單地在資料庫這個層面上完成對於應用資料的安全性保護,而如果透過SYS_CONTEXT以及資料庫登入觸發器來編寫更加複雜的VPD策略函式的話,就能實現非常強大的資料安全性功能。

後續:
Oracle資料庫安全領域有很多我還沒有接觸到的東西需要學習,下面一篇文章我將會介紹同樣是基於VPD的更深一步的安全策略解決方案 - Label Security,敬請期待。

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

相關文章