操作计划
这个计划是很复杂的,也是可改变的:
- 识别 VPD 将保护的表。
- 识别需要保护的表的列。
- 识别限制条件,例如,Salaries > 1000。
- 识别如何建立权限——例如,用户具备授权级别或角色吗? 您可能希望将用户分为三组,每组都有相关的授权级别。 或者,可能您想根据角色对用户群的访问限制进行分配——经理可以访问所有的行,职员可以访问超过 SALARY > 2000 行,等等。
- 决定您如何通过包变量、应用程序环境,或者静态表将权限传给策略函数。
- 如果需要创建更多的索引,请进行识别。
- 创建额外的索引。
- 识别子表,决定一个方案来启动通过新列或 IN 条件对子表的限制。
- 根据以上决定重新识别对索引的需求。
- 创建索引。
- 构建策略函数。
- 创建策略(但是禁止)。
- 在某个轻松活动的一天里,启动该策略和测试,使用常规用户账户访问该表以确保该策略的运行。 如果该策略不运行,请检查跟踪文件以找到错误。
- 如果该策略不运行,请启动该策略。
- 监控性能。
- 识别更多需求以构建索引,使用大纲,等等。
- 迭代所有表。
4.3 屏蔽敏感的列
背景 把您自己想象成为一名业余数据库黑客。 这里的数据库包含医疗记录,您正在寻找的信息是诊断代码。 您将寻找哪些列? 可能是称为诊断、疾病或者类似的列。
正如您可以看到的,带有明显名字的敏感列是至关重要的安全问题。 策略 如果对手以前不了解您数据库的内容,并且这些列的名字不直观,他们将不会去解读列的含义。 这个策略称为“无名安全”。 即使故意闯进数据库的经验丰富的黑客在做其它事情之前仍将需要追捕到列的名称。 因为他们的时间可能有限——几乎一直都是这样——他们通常会转到下一个机会上。 当然,使用无名列也加大了开发的难度。
进行折衷还有其它的办法,然而: 通过列屏蔽,您可以隐藏列的内容,只有合法用户才可以看到列的内容。
列屏蔽的方法有两种: 使用视图和使用 VPD。
使用视图。 这种方法适用于 Oracle 任何版本,但是如果您的数据库版本是 Oracle9i 或者更早,就只能选择这种方法。
假设您的表和以下类似: SQL> desc patient_diagnosis
Name Null?类型
------------------- ------ -------------
PATIENT_ID NUMBER
DIAGNOSIS_ID NUMBER
DIAGNOSIS_CODE VARCHAR2(2)
DOCTOR_ID NUMBER(2)
BILLING_CODE NUMBER(10)
行类和以下类似: SQL> select * from patient_diagnosis;
PATIENT_ID DIAGNOSIS_ID DI DOCTOR_ID BILLING_CODE
---------- ------------ -- ---------- ------------
1 1 01 1 1003
1 2 02 1 1003
1 3 11 1 1003
2 1 11 1 1005
2 2 41 2 1005
在这里,您想屏蔽列 DIAGNOSIS_CODE 的值。 create view vw_patient_disgnosis
as
select
patient_id,
diagnosis_id,
doctor_id,
billing_code
from patient_diagnosis
/
然后,您可以给视图 VW_PATIENT_DIAGNOSIS 创建同义词 PATIENT_DIAGNOSIS,授予视图(而不是表)选择。 该视图屏蔽列 DIAGNOSIS_CODE。
这是一个相当简单的解决方案,因此您不要将所有用户的列屏蔽掉,您可能想创建基于角色的匿名——如果用户是一名经理,请显示被保护的列;否则的话不要显示。其方法是:传递应用程序环境或者全球变量以指定用户的角色。 如果应用程序环境属性是 IS_MANAGER,您可以使用: create or replace view vw_patient_disgnosis
as
select
patient_id,
diagnosis_id,
decode(
sys_context('USER_ROLE_CTX','IS_MANAGER'),
'Y', DIAGNOSIS_CODE, null
) diagnosis_code,
doctor_id,
billing_code
from patient_diagnosis;
这是一个更加灵活的视图,该视图可以授权给所有的用户,该视图的内容会随着用户角色的不同而不同。
使用 VPD。 Oracle 数据库 10g 中引入的新特性使 VPD 更加有用: 创建视图是没有必要的。 相反,VPD 策略可能抑制显示。 这里,VPD 策略函数和以下类似: 1 create or replace function pd_pol
2 (
3 p_schema in varchar2,
4 p_obj in varchar2
5 )
6 return varchar2
7 is
8 l_ret varchar2(2000);
9 begin
10 if (p_schema = USER) then
11 l_ret := NULL;
12 else
13 l_ret := '1=2';
14 end if;
15 return l_ret;
16 end;
现在构建策略函数: 1 begin
2 dbms_rls.add_policy (
3 object_schema => 'ARUP',
4 object_name => 'PATIENT_DIAGNOSIS',
5 policy_name => 'PD_POL',
6 policy_function => 'PD_POL',
7 statement_types => 'SELECT',
8 update_check => TRUE,
9 sec_relevant_cols => 'DIAGNOSIS_CODE',
10 sec_relevant_cols_opt => dbms_rls.all_rows
11 );
12 end;
注意行号 9 和 10。在第 9 行中,我们提及将列 DIAGNOSIS_CODE 作为敏感列。 在第 10 行中,我们指出如果选择了该列,VPD 显示所有列;但是该列值却显示为 NULL。 这就有效地屏蔽了该列。 在策略函数中,请注意如果表的所有者进行选择,应用的谓词为 NULL。因此,VPD 限制就不被应用,列也不显示。
请记住,没有“更换”策略的方法。 如果旧策略还存在,您必须首先抛弃旧策略。 begin
dbms_rls.drop_policy (
object_schema => 'ARUP',
object_name => 'PATIENT_DIAGNOSIS',
policy_name => 'PD_POL'
);
end;
现在,您可以进行测试。 SQL> conn arup/arup
Connected.
SQL> select * from patient_diagnosis;
PATIENT_ID DIAGNOSIS_ID DI DOCTOR_ID BILLING_CODE
---------- ------------ -- ---------- ------------
1 1 01 1 1003
1 2 02 1 1003
1 3 11 1 1003
2 1 11 1 1005
2 2 41 2 1005
注意:DIAGNOSIS_CODE 列值显示出来了,因为 ARUP 是表的所有者,ARUP 应该看得到这些值。 现在,以对该表有选择权限的另一名用户身份进行连接,执行相同的查询。 SQL> set null ?
SQL> conn ananda/ananda
SQL> select * from arup.patient_diagnosis;
PATIENT_ID DIAGNOSIS_ID D DOCTOR_ID BILLING_CODE
---------- ------------ - ---------- ------------
1 1 ? 1 1003
1 2 ? 1 1003
1 3 ? 1 1003
2 1 ? 1 1005
2 2 ? 2 1005
注意列 DIAGNOSIS_CODE 是如何显示所有空值的。
(编辑:aniston)
|