Dec
24
2006
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,敬请期待。
Oracle 


VPD 


Dec
18
2006
五爷的blog上提到了Cyril,这个活跃在日本的街头魔术师确实是神一般的人。
就地取材,在众目睽睽之下让你目瞪口呆,然后Cyril扬长而去。
在China Town的那一场,Cyril变没了一只鹦鹉,然后从旁边的杂货店里取了一个鸡蛋和一个柠檬,将鸡蛋变没了,然后取了一个桔子,把手边的柠檬变没了,至此为止也许还无惊人之处,大多数街头魔术师或许都可以轻而易举地实现这些。但是,接下来,Cyril取出一把刀,切开了桔子,取出了刚才那个柠檬!再切开柠檬,取出了刚才那个鸡蛋,最后捏碎鸡蛋,变回了最初的那只鹦鹉。
除了五爷blog里面给出的4段惊天地泣鬼神的video,这里还有更多。
虽然我无法相信这只是魔术,但是我仍然只能相信这是魔术。
BTW:五爷为什么会让人觉得狂,因为五爷哪怕只是在传播知识的时候,也要嘲笑打击他人。如果我们做到笑骂由人的话,五爷还是可爱的。:)
再BTW:to 五爷,我给的链接里面Boat trick是你那个第三段video的增强版,因为更加不可能实现,场所是在水底!而且最后隔窗取物!
No Tags