更多精彩内容尽在www.leonarding.com
1.什么是VPD:Virtual 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_name和filter_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是一种行级安全控制,操作简单无需添加任何组件即可实施。
Leonarding
2013.6.14
北京&summer
分享技术~成就梦想
Blog:www.leonarding.com