="t18">
5种类型
![](/icons/18459de.gif)
策略、列相关策略以及列屏蔽使得 VPD 成为 DBA
![](/icons/18459de.gif)
安全工具箱中
![](/icons/18459yi.gif)
种功能更加强大
![](/icons/18459de.gif)
工具
虚拟专用数据库 (VPD) 也称为细粒度访问控制
![](/icons/18459dou.gif)
它提供强大
![](/icons/18459de.gif)
行级安全功能
![](/icons/18459dou2.gif)
它是在 Oracle8i 中推出
![](/icons/18459de.gif)
![](/icons/18459dou.gif)
已经受到广泛
![](/icons/18459de.gif)
欢迎
![](/icons/18459dou.gif)
并且在从教育软件Software到金融服务等各种应用
![](/icons/18459chengxu.gif)
得到采用
VPD
![](/icons/18459de.gif)
工作思路方法是
![](/icons/18459dou.gif)
通过透明地更改对数据
![](/icons/18459de.gif)
请求
![](/icons/18459dou.gif)
基于
![](/icons/18459yi.gif)
系列定义
![](/icons/18459de.gif)
标准向用户提供表
![](/icons/18459de.gif)
局部视图
![](/icons/18459dou2.gif)
在运行时
![](/icons/18459dou.gif)
所有查询都附加了谓词
![](/icons/18459dou.gif)
以便筛选出准许用户看到
![](/icons/18459de.gif)
行
![](/icons/18459dou2.gif)
例如
![](/icons/18459dou.gif)
假如只答应用户查看帐户治理员 SCOTT
![](/icons/18459de.gif)
帐户
![](/icons/18459dou.gif)
则 VPD 设置自动地将查询:
select * from accounts;
重写为:
select * from accounts
where am_name = 'SCOTT';
DBA 在表 ACCOUNTS 上设置了
![](/icons/18459yi.gif)
项安全策略
![](/icons/18459dou2.gif)
该策略具有
![](/icons/18459yi.gif)
个相关
![](/icons/18459hanshu.gif)
![](/icons/18459dou.gif)
称为policy function
![](/icons/18459dou.gif)
它返回
![](/icons/18459yi.gif)
个用作谓词
![](/icons/18459de.gif)
![](/icons/18459zifu.gif)
串 where am_name = 'SCOTT'
![](/icons/18459dou2.gif)
假如您不熟悉该特性
![](/icons/18459de.gif)
全部功能
![](/icons/18459dou.gif)
我建议您阅读 Oracle 杂志
![](/icons/18459de.gif)
文章“利用 VPD 保持信息
![](/icons/18459de.gif)
私密性”
策略类型 生成谓词所需
![](/icons/18459de.gif)
重复分析是
![](/icons/18459yi.gif)
种在某些情况下可以进行修整
![](/icons/18459de.gif)
开销
![](/icons/18459dou2.gif)
例如
![](/icons/18459dou.gif)
在大部分实际情况中
![](/icons/18459dou.gif)
谓词并不象 am_name = 'SCOTT' 那样是静态
![](/icons/18459de.gif)
;它基于用户
![](/icons/18459de.gif)
身份、用户
![](/icons/18459de.gif)
权限级别、用户向哪个帐户治理员进行报告等情况,可能更具有动态性
![](/icons/18459dou2.gif)
由策略
![](/icons/18459hanshu.gif)
创建并返回
![](/icons/18459de.gif)
![](/icons/18459zifu.gif)
串可能会具有很强
![](/icons/18459de.gif)
动态性
![](/icons/18459dou.gif)
而为了保证其结果
![](/icons/18459dou.gif)
Oracle 必须每次重新执行策略
![](/icons/18459hanshu.gif)
![](/icons/18459dou.gif)
既浪费资源又降低性能
![](/icons/18459dou2.gif)
在这种类型
![](/icons/18459de.gif)
策略中
![](/icons/18459dou.gif)
谓词每次执行时可能会有很大
![](/icons/18459de.gif)
差别
![](/icons/18459dou.gif)
该策略称为“动态”策略
![](/icons/18459dou.gif)
在 Oracle9i 数据库以及以前
![](/icons/18459de.gif)
版本中已经提供了这种策略
除了保留动态策略的外
![](/icons/18459dou.gif)
Oracle 数据库 10g 还基于谓词
![](/icons/18459de.gif)
构造推出了几种新类型
![](/icons/18459de.gif)
策略
![](/icons/18459dou.gif)
为提高性能提供了更好
![](/icons/18459de.gif)
控制:context_sensitive、shared_context_sensitive、shared_
![](/icons/18459static.gif)
和
![](/icons/18459static.gif)
![](/icons/18459dou2.gif)
现在
![](/icons/18459dou.gif)
让我们来了解每种策略类型
![](/icons/18459de.gif)
意义以及如何在适当
![](/icons/18459de.gif)
场合中使用它们
动态策略
![](/icons/18459dou2.gif)
为保持向后兼容性
![](/icons/18459dou.gif)
10g 中
![](/icons/18459de.gif)
默认策略类型为“dynamic” — 正如 Oracle9i 中
![](/icons/18459yi.gif)
样
![](/icons/18459dou2.gif)
在这种情况下
![](/icons/18459dou.gif)
对于每行以及每位用户
![](/icons/18459dou.gif)
在每次访问表时都对策略
![](/icons/18459hanshu.gif)
进行重新求值
![](/icons/18459dou2.gif)
让我们来具体分析策略谓词:
where am_name = 'SCOTT'
忽略掉 where 子句
![](/icons/18459dou.gif)
谓词就具有两个区别
![](/icons/18459de.gif)
部分:在等式操作符的前
![](/icons/18459de.gif)
部分 (am_name) 和等式操作符的后
![](/icons/18459de.gif)
部分 ('SCOTT')
![](/icons/18459dou2.gif)
在大多数情况下
![](/icons/18459dou.gif)
后面
![](/icons/18459de.gif)
部分更象是变量
![](/icons/18459dou.gif)
![](/icons/18459yinwei.gif)
它是由用户
![](/icons/18459de.gif)
数据提供
![](/icons/18459de.gif)
(假如用户是 SCOTT
![](/icons/18459dou.gif)
则其值为 'SCOTT')
![](/icons/18459dou2.gif)
在等号前面
![](/icons/18459de.gif)
部分是静态
![](/icons/18459de.gif)
![](/icons/18459dou2.gif)
因此
![](/icons/18459dou.gif)
即使
![](/icons/18459hanshu.gif)
不必为生成适当
![](/icons/18459de.gif)
谓词而对每行求出策略
![](/icons/18459hanshu.gif)
![](/icons/18459de.gif)
值
![](/icons/18459dou.gif)
由于了解前面部分
![](/icons/18459de.gif)
静态性以及后面部分
![](/icons/18459de.gif)
动态性
![](/icons/18459dou.gif)
也可以提高性能
![](/icons/18459dou2.gif)
在 10g 中
![](/icons/18459dou.gif)
可以在 dbms_rls.add_policy
![](/icons/18459diaoyong.gif)
中使用 "context_sensitive" 类型
![](/icons/18459de.gif)
策略作为参数来实现这种思路方法:
policy_type => dbms_rls.context_sensitive
在另
![](/icons/18459yi.gif)
个举例中
![](/icons/18459dou.gif)
我们有
![](/icons/18459yi.gif)
个称为 ACCOUNTS
![](/icons/18459de.gif)
表
![](/icons/18459dou.gif)
它拥有几列
![](/icons/18459dou.gif)
其中
![](/icons/18459yi.gif)
列是 BALANCE
![](/icons/18459dou.gif)
表示帐户余额
![](/icons/18459dou2.gif)
假设答应某个用户查看低于某特定余额
![](/icons/18459de.gif)
帐户
![](/icons/18459dou.gif)
而该余额由应用
![](/icons/18459chengxu.gif)
上下文所决定
![](/icons/18459dou2.gif)
我们并不在策略
![](/icons/18459hanshu.gif)
中将此余额值固定
![](/icons/18459dou.gif)
而是3是根据应用
![](/icons/18459chengxu.gif)
上下文确定
![](/icons/18459dou.gif)
如:
create or replace vpd_pol_func
(
p_schema in varchar2,
p_table in varchar2
)
![](/icons/18459return.gif)
varchar2
is
begin
![](/icons/18459return.gif)
'balance < sys_context(''vpdctx'', ''maxbal'')';
end;
应用
![](/icons/18459chengxu.gif)
上下文 VPDCTX
![](/icons/18459de.gif)
属性 MAXBAL 可以在会话
![](/icons/18459de.gif)
前期设定
![](/icons/18459dou.gif)
而
![](/icons/18459hanshu.gif)
在运行时可以轻易地获得该数值
请仔细注重该举例
![](/icons/18459dou2.gif)
谓词有两部分:小于号的前
![](/icons/18459de.gif)
部分和的后
![](/icons/18459de.gif)
部分
![](/icons/18459dou2.gif)
的前
![](/icons/18459de.gif)
部分是“balance”
![](/icons/18459yi.gif)
词
![](/icons/18459dou.gif)
它是文
![](/icons/18459zifu.gif)
![](/icons/18459dou2.gif)
后面
![](/icons/18459de.gif)
部分从某种程度而言是静态
![](/icons/18459de.gif)
![](/icons/18459dou.gif)
![](/icons/18459yinwei.gif)
应用
![](/icons/18459chengxu.gif)
上下文变量在改变的前
![](/icons/18459yi.gif)
直是常量
![](/icons/18459dou2.gif)
假如应用
![](/icons/18459chengxu.gif)
上下文属性不变
![](/icons/18459dou.gif)
则整个谓词是常量
![](/icons/18459dou.gif)
因此不需要重新执行
![](/icons/18459hanshu.gif)
![](/icons/18459dou2.gif)
假如策略类型定义为对上下文敏感
![](/icons/18459dou.gif)
则 Oracle 数据库 10g 可以识别此情况以用于优化
![](/icons/18459dou2.gif)
假如在会话期间没有发生会话上下文
![](/icons/18459de.gif)
变化
![](/icons/18459dou.gif)
则不重新执行该
![](/icons/18459hanshu.gif)
![](/icons/18459dou.gif)
从而显著提高了性能
静态策略
![](/icons/18459dou2.gif)
有时业务操作可以确保谓词更加静态
![](/icons/18459dou2.gif)
例如
![](/icons/18459dou.gif)
在上下文敏感
![](/icons/18459de.gif)
策略类型举例中
![](/icons/18459dou.gif)
我们将用户所见
![](/icons/18459de.gif)
最大余额定义为
![](/icons/18459yi.gif)
个变量
![](/icons/18459dou2.gif)
当 web 应用
![](/icons/18459chengxu.gif)
中
![](/icons/18459de.gif)
Oracle userid 由许多 web 用户共享
![](/icons/18459dou.gif)
并且应用
![](/icons/18459chengxu.gif)
基于这些用户
![](/icons/18459de.gif)
权限来设置该变量(应用
![](/icons/18459chengxu.gif)
上下文)时
![](/icons/18459dou.gif)
这种思路方法很有用
![](/icons/18459dou2.gif)
因此
![](/icons/18459dou.gif)
web 用户 TAO 和 KARTHIK 都是以用户 APPUSER 连接到数据库
![](/icons/18459de.gif)
![](/icons/18459dou.gif)
2者可以在其会话中拥有两个区别
![](/icons/18459de.gif)
应用
![](/icons/18459chengxu.gif)
上下文
![](/icons/18459de.gif)
值
![](/icons/18459dou2.gif)
此时 MAXBAL
![](/icons/18459de.gif)
值并不依靠于 Oracle userid
![](/icons/18459dou.gif)
而是依靠 TAO 和 KARTHIK 各自
![](/icons/18459de.gif)
会话
在静态策略
![](/icons/18459de.gif)
情况下
![](/icons/18459dou.gif)
谓词更具有可猜测性
![](/icons/18459dou.gif)
其介绍说明如下
LORA 和 MICHELLE 分别是 Acme Bearings 和 Goldtone Bearings
![](/icons/18459de.gif)
帐户治理员
![](/icons/18459dou2.gif)
当他们连接数据库时
![](/icons/18459dou.gif)
他们使用自己
![](/icons/18459de.gif)
id
![](/icons/18459dou.gif)
并且只应该看到属于他们
![](/icons/18459de.gif)
那些行
![](/icons/18459dou2.gif)
在 Lora 方面
![](/icons/18459dou.gif)
谓词变成 where CUST_NAME = 'ACME';而对于 Michelle
![](/icons/18459dou.gif)
则是 where CUST_NAME = 'GOLDTONE'
![](/icons/18459dou2.gif)
在这里
![](/icons/18459dou.gif)
谓词依靠于他们
![](/icons/18459de.gif)
userid
![](/icons/18459dou.gif)
因此他们所创建
![](/icons/18459de.gif)
任何会话在应用
![](/icons/18459chengxu.gif)
上下文中始终具有相同
![](/icons/18459de.gif)
值
10g 可以利用这种情况
![](/icons/18459dou.gif)
在 SGA 中对谓词进行高速缓存Cache
![](/icons/18459dou.gif)
并在会话中重用该谓词
![](/icons/18459dou.gif)
而不必重新执行策略
![](/icons/18459hanshu.gif)
![](/icons/18459dou2.gif)
策略
![](/icons/18459hanshu.gif)
类似于以下形式:
create or replace vpd_pol_func
(
p_schema in varchar2,
p_table in varchar2
)
![](/icons/18459return.gif)
varchar2
is
begin
![](/icons/18459return.gif)
'cust_name = sys_context(''vpdctx'', ''cust_name'')';
end;
而策略定义为:
policy_type => dbms_rls.
这种思路方法确保策略
![](/icons/18459hanshu.gif)
只执行
![](/icons/18459yi.gif)
次
![](/icons/18459dou2.gif)
即使应用
![](/icons/18459chengxu.gif)
上下文在会话中改变
![](/icons/18459dou.gif)
也从不重新执行该
![](/icons/18459hanshu.gif)
![](/icons/18459dou.gif)
使得此过程
![](/icons/18459de.gif)
速度非常快
建议将静态策略用于在几个用户中托管应用
![](/icons/18459chengxu.gif)
![](/icons/18459de.gif)
情况
![](/icons/18459dou2.gif)
在这种情况下
![](/icons/18459dou.gif)
单个数据库拥有几个用户
![](/icons/18459de.gif)
数据
![](/icons/18459dou2.gif)
当每个用户登录时
![](/icons/18459dou.gif)
登录后触发器可以设置用于策略
![](/icons/18459hanshu.gif)
![](/icons/18459de.gif)
应用
![](/icons/18459chengxu.gif)
上下文
![](/icons/18459de.gif)
值
![](/icons/18459dou.gif)
以便快速生成谓词
但是
![](/icons/18459dou.gif)
将策略定义为静态也是
![](/icons/18459yi.gif)
把双刃剑
![](/icons/18459dou2.gif)
在以上
![](/icons/18459de.gif)
举例中
![](/icons/18459dou.gif)
我们假设应用
![](/icons/18459chengxu.gif)
上下文属性 VPDCTX.CUST_NAME
![](/icons/18459de.gif)
值在会话中不改变
![](/icons/18459dou2.gif)
假如这种假设不正确
![](/icons/18459dou.gif)
将会怎样呢?假如该值改变
![](/icons/18459dou.gif)
策略
![](/icons/18459hanshu.gif)
将不会执行
![](/icons/18459dou.gif)
因此在谓词中将不会使用新值
![](/icons/18459dou.gif)
而返回
![](/icons/18459cuowu.gif)
![](/icons/18459de.gif)
结果!因此
![](/icons/18459dou.gif)
在将策略定义为静态时要非常小心;您必须绝对确信该值不会改变
![](/icons/18459dou2.gif)
假如您不能作这种假设
![](/icons/18459dou.gif)
则最好将策略定义为对上下文敏感
共享策略类型
![](/icons/18459dou2.gif)
为了重用代码并最大限度地利用已经分析过
![](/icons/18459de.gif)
代码
![](/icons/18459dou.gif)
您可以决定为几个表使用通用
![](/icons/18459de.gif)
策略
![](/icons/18459hanshu.gif)
![](/icons/18459dou2.gif)
例如
![](/icons/18459dou.gif)
在上述举例中
![](/icons/18459dou.gif)
我们可能对于区别类型
![](/icons/18459de.gif)
帐户拥有区别
![](/icons/18459de.gif)
表 — SAVINGS 和 CHECKING — 但是规则仍然是相同
![](/icons/18459de.gif)
:限制用户查看余额超过其授权范围
![](/icons/18459de.gif)
帐户
![](/icons/18459dou2.gif)
这种情况要求为 CHECKING 和 SAVINGS 表上
![](/icons/18459de.gif)
策略使用统
![](/icons/18459yi.gif)
![](/icons/18459de.gif)
![](/icons/18459hanshu.gif)
![](/icons/18459dou2.gif)
该策略创建为 context_sensitive
假设事件按如下顺序发生:
1. 连接会话
2. 设置应用
![](/icons/18459chengxu.gif)
上下文
3. select * from savings;
4. select * from checking;
即使应用
![](/icons/18459chengxu.gif)
上下文在第 3 步和第 4 步的间没有改变
![](/icons/18459dou.gif)
策略
![](/icons/18459hanshu.gif)
也会重新执行
![](/icons/18459dou.gif)
![](/icons/18459yinwei.gif)
现在所选择
![](/icons/18459de.gif)
表已经区别
![](/icons/18459dou2.gif)
这不是我们所希望
![](/icons/18459de.gif)
情况
![](/icons/18459dou.gif)
![](/icons/18459yinwei.gif)
策略
![](/icons/18459hanshu.gif)
相同
![](/icons/18459dou.gif)
不需要重新执行该
![](/icons/18459hanshu.gif)
10g 中
![](/icons/18459de.gif)
新功能是能够在对象间共享策略
![](/icons/18459dou2.gif)
在上述举例中
![](/icons/18459dou.gif)
您可以将这些策略
![](/icons/18459de.gif)
策略类型定义为:
policy_type => dbms_rls.shared_context_sensitive
将策略声明为 "shared" 可以在以上所示
![](/icons/18459de.gif)
情况中不再执行该
![](/icons/18459hanshu.gif)
![](/icons/18459dou.gif)
从而提高了性能
选择性
列 现在设想
![](/icons/18459yi.gif)
种情况
![](/icons/18459dou.gif)
只有在选择了特定列时才会应用 VPD 策略
![](/icons/18459dou2.gif)
在上述举例
![](/icons/18459de.gif)
表 ACCOUNTS 中
![](/icons/18459dou.gif)
各行如下所示:
ACCTNO ACCT_NAME BALANCE
------ ------------ -------
1 BILL CAMP 1000
2 TOM CONNOPHY 2000
3 ISRAEL D 1500
不答应 Michelle 查看余额超过 1600
![](/icons/18459de.gif)
帐户
![](/icons/18459dou2.gif)
当她执行类似以下
![](/icons/18459de.gif)
查询时:
select * from accounts;
将看到:
ACCTNO ACCT_NAME BALANCE
------ ------------ -------
1 BILL CAMP 1000
3 ISRAEL D 1500
acctno 2
![](/icons/18459de.gif)
余额超过 1600
![](/icons/18459dou.gif)
它已禁止显示
![](/icons/18459dou2.gif)
对于 Michelle 而言
![](/icons/18459dou.gif)
表中只有两行
![](/icons/18459dou.gif)
而不是 3行
![](/icons/18459dou2.gif)
当她执行类似以下
![](/icons/18459de.gif)
查询时:
select count(*) from accounts;
该查询只计算表中
![](/icons/18459de.gif)
记录数
![](/icons/18459dou.gif)
输出是 2
![](/icons/18459dou.gif)
而不是 3
但是
![](/icons/18459dou.gif)
此时我们可以决定将安全策略稍微放松
![](/icons/18459yi.gif)
些
![](/icons/18459dou2.gif)
在本查询中
![](/icons/18459dou.gif)
Michelle 不能查看帐户余额等秘密数据;她只是计算表中所有记录
![](/icons/18459de.gif)
数目
![](/icons/18459dou2.gif)
在和安全策略
![](/icons/18459yi.gif)
致
![](/icons/18459de.gif)
情况下
![](/icons/18459dou.gif)
我们可以答应此查询计算所有记录
![](/icons/18459de.gif)
数目
![](/icons/18459dou.gif)
无论是否答应她查看这些记录
![](/icons/18459dou2.gif)
假如需要这样
![](/icons/18459dou.gif)
则在对 10g
![](/icons/18459de.gif)
dbms_rls.add_policy
![](/icons/18459de.gif)
![](/icons/18459diaoyong.gif)
中
![](/icons/18459de.gif)
另
![](/icons/18459yi.gif)
个参数答应实现此功能:
sec_relevant_cols => 'BALANCE'
现在
![](/icons/18459dou.gif)
当用户选择列 BALANCE 时
![](/icons/18459dou.gif)
无论是显式选择还是隐含在 select * 中
![](/icons/18459dou.gif)
VPD 策略都会介入
![](/icons/18459dou.gif)
对行作出限制
![](/icons/18459dou2.gif)
否则将会选择表中所有
![](/icons/18459de.gif)
行
![](/icons/18459dou.gif)
![](/icons/18459yinwei.gif)
在查询中用户只选择了总计行数
![](/icons/18459dou.gif)
而没有选择列 BALANCE
![](/icons/18459dou2.gif)
假如将以上参数设置为所示
![](/icons/18459de.gif)
形式
![](/icons/18459dou.gif)
则查询
select count(*) from accounts;
将显示 3列
![](/icons/18459dou.gif)
而不是两列
![](/icons/18459dou2.gif)
但是查询:
select * from accounts;
延伸阅读
最新评论