正如您可以看到的,每个用户 ID 都设置了相应的级别。 现在,您可以在表上构建 VPD。 您可以使用所提供的 PL/SQL 包 DBMS_RLS 控制整个 VPD 基础架构;一个称为策略的概念控制着决定应该显示哪些行的规则。 策略将“谓词”(WHERE 条件)应用到表中的所有查询上,有效地限制了对行的访问。 一个称为策略函数的函数生成 WHERE 条件。 因此,首先我们必须创建策略函数,该函数返回 WHERE 条件以将该条件应用到查询中。 create or replace function get_acc_max_bal
(
p_schema in varchar2,
p_obj in varchar2
)
return varchar2
as
l_ret varchar2(2000);
begin
select
case userlevel
when 1 then 'acc_bal <= 1000'
when 2 then 'acc_bal <= 1200'
when 3 then null
else
'1=2'
end
into l_ret
from userlevels
where username = 'HR'
return l_ret;
end;
然后添加策略: begin
dbms_rls.add_policy (
object_name => 'EMP',
policy_name => 'ACCOUNTS_ACCESS',
policy_function => 'USER_ONLY',
statement_types => 'INSERT, UPDATE, DELETE, SELECT',
update_check => TRUE
);
end;
这次表得到保护。 当 CLERK1 登录并从表中进行选择: SQL> select * from arup.accounts;
ACCNO ACC_NAME ACC_BAL
---------- -------------------- ----------
1 John 1000
Clerk1 只能看到 ACCNO 1,余额为 1,000。因为没有授予 Clerk1 查看高于 1,000 的账户余额,所以他看不到其它账户。 但是,当 Clerk2 登录时: SQL> conn clerk2/clerk2
Connected.
SQL> select * from arup.accounts;
ACCNO ACC_NAME ACC_BAL
---------- -------------------- ----------
1 John 1000
2 Joe 1200
她也可以看到 ACCNO 2。 ACCNO 2 的余额为 1,200,在给 Clerk2 的授权限制之内。
您可以使用该技术将被限制的视图类放到表中。 在项目锁定中,这将是一个很方便的工具。
策略 关键是找出各方面的哪些信息将被保护,哪些列上的信息将被保护。 这听起来很简单,但是实际做起来是很难的。 收集该信息需要商业知识,或者合作者至少要更熟悉那些过程。 一旦您识别到表和列,您应该能够按照以上背景部分中示例中显示的那样实施 VPD 策略。
即使 VPD 是很效的,如果您想让一些用户可以不受限制就可以访问表怎么办? 角色 EXEMPT ACCESS POLICY 的确是这样做的。 grant exempt access policy to ananda;
从此处开始,ANANDA 将跳过在所有表中定义的所有访问策略。
使用户跳过所有访问限制可能是不可接受的,然而,一个更好的解决方案是在策略函数中对其进行编码。 一个很好的示例就是表的模式所有者——无疑您想该所有者看到表的所有行而不受到限制。 您可以在策略函数中对其进行如下编码: create or replace function get_acc_max_bal
(
p_schema in varchar2,
p_obj in varchar2
)
return varchar2
as
l_ret varchar2(2000);
begin
if (p_schema = USER) then
l_ret := NULL;
else
select
case userlevel
when 1 then 'acc_bal <= 1000'
when 2 then 'acc_bal <= 1200'
when 3 then null
else
'1=2'
end
into l_ret
from userlevels
where username = 'HR'
end if;
return l_ret;
end;
当表的所有者登录 (p_schema = USER) 时,该版本函数返回 NULL,所以对表的访问不受限制。 当然,您可以在该函数中进行任意更改,以允许更多用户跳过 VPD 策略。
VPD 的最大挑战是对子表进行限制。 您的限制条件可能在称为 ACC_BAL 的列上;但是所有其它子表不可能有该列。 因此,您如何限制那些表?
例如,这里有一个称为地址的表,该表包含这些客户的地址。 该表没有称为 ACC_BAL 的列,因此您如何对该表设置和 ACCOUNTS 表一样的限制? 有如下两种方式:
您必须按照自己所处的环境从这两种方法中选取一种。
提示 几个潜在破环性提示如下:
- VPD 运行的方式是重写查询以添加额外的谓词。 用户查询可能写得很好,可能调整得很好,但是引入额外的谓词却带来了破坏,因为优化计划可能改变。 您应该仔细考虑潜在的影响,通过建立索引降低风险。
- 物化视图工作的方式是从底层表中选择行。 如果视图的模式所有者不受限制就可以访问该表,则只有那些和 VPD 策略一致的行才会被刷新,使视图不精确。
- 如果您已经设置了复制,从事传播和接收工作的用户应该可以不受限制地对表进行访问。否则,他们只能复制表中的一部分。
- 如果您使用直接路径插入(使用 APPEND 提示插入)对该表进行加载,那么您在该表上不可能有 VPD 策略。 使用可以不受限制地对表访问的用户,您应该临时禁止该策略,或进行插入。
- 直接路径导出跳过 SQL 层;因此,VPD 策略不会被应用。 所以,当您使用 DIRECT=Y 选项导出表时,Oracle 忽略该表,并且使用常规路径导出该表。 这可能增加整个执行时间。
操作计划
这个计划是很复杂的,也是可改变的:
- 识别 VPD 将保护的表。
- 识别需要保护的表的列。
- 识别限制条件,例如,Salaries > 1000。
- 识别如何建立权限——例如,用户具备授权级别或角色吗? 您可能希望将用户分为三组,每组都有相关的授权级别。 或者,可能您想根据角色对用户群的访问限制进行分配——经理可以访问所有的行,职员可以访问超过 SALARY > 2000 行,等等。
- 决定您如何通过包变量、应用程序环境,或者静态表将权限传给策略函数。
- 如果需要创建更多的索引,请进行识别。
- 创建额外的索引。
- 识别子表,决定一个方案来启动通过新列或 IN 条件对子表的限制。
- 根据以上决定重新识别对索引的需求。
- 创建索引。
- 构建策略函数。
- 创建策略(但是禁止)。
- 在某个轻松活动的一天里,启动该策略和测试,使用常规用户账户访问该表以确保该策略的运行。 如果该策略不运行,请检查跟踪文件以找到错误。
- 如果该策略不运行,请启动该策略。
- 监控性能。
- 识别更多需求以构建索引,使用大纲,等等。
- 迭代所有表。
(编辑:aniston)
|