前几周初略学习了Oracle的VPD技,做了几个试验,也在EBS系统上测试了一下。总结如下,有些内容摘自网络。
在数据库的数据安全访问的解决上,有很多的方法来解决权限的问题,常用的方法例如建立视图的方法控制,例如查询语句中加where语句来控制。用view的方法在表结构或者权限变更的时候很不容易操作,编码工作量大、系统适应用户管理体系的弹性空间较小,一旦权限逻辑发生变动,就可能需要修改权限体系,导致所有的View都必须修改;用where语句可以解决问题但是安全性不好,只能在应用程序级别才能控制,绕开应用程序就无法控制。
Oracle VPD 技术在数据库级别的安全控制有效的解决了数据访问操作的权限问题,可以对数据库对象进行访问控制,可以灵活的隔离数据,oracle已经实现了VPD,可以直接使用,比在应用层权限控制实现起来较方便,权限维护也比容易。
VPD访问控制原理也是使用where语句来控制,只是这个where语句是数据库在操作数据时自动拼接,不是在应用层拼接,而且由事先定义的策略来决定是否拼接条件语句。主要步骤是:
(1) 编写function, 函数返回拼接在DML语句的where条件之后的语句,但是where语句并不是执行DML时可见的,系统根绝策略自动添加的,条件来自策略函数的返回值。例如:
表:apps.t_policy( T1 VARCHAR2(10 BYTE), T2 NUMBER(10) )
策略函数:
Create or replace function Fn_GetPolicy(
P_Schema In Varchar2,
P_Object In Varchar2)
return varchar2 is
Result varchar2(1000);
begin
Result:='t2 not in (10)';
return(Result);
end Fn_GetPolicy;
/
(2) 在oracle数据库中添加策略
策略定义在系统中,由DBA维护,应用开发时可根据需要定义策略。例如根据上面的表和策略函数,定义策略如下:
declare
Begin
Dbms_Rls.Add_Policy(
Object_Schema =>'apps', --数据表(或视图)所在的Schema名称
Object_Name =>'T_Policy', --数据表(或视图)的名称
Policy_Name =>'T_TestPolicy', --POLICY的名称,主要用于将来对Policy的管理
Function_Schema =>'apps', --返回Where子句的函数所在Schema名称
Policy_Function =>'Fn_GetPolicy', --返回Where子句的函数名称
Statement_Types =>'Select', -- DML类型,如 'Select,Insert,Update,Delete'
Enable =>True --是否启用,值为'True'或'False'
);
end;
/
这样,在查询T_Policy这个表的时候,就可以根据策略函数的条件来控制访问了。
DBMS_RLS内置函数包
Dbms_rls包含很多维护表,视图,同义词安全策略的函数,要使用dbms_rls的数据库用户必须有sys.dbms_rls的execute权限。常用dbms_rls函数有:
ADD_POLICY 将访问控制策略添加到对象
DROP_POLICY 删除对象中的策略
REFRESH_POLICY 重新解析与策略关联的、缓存的所有语句
ENABLE_POLICY 启用或禁用策略
CREATE_POLICY_GROUP 创建策略组
ADD_GROUPED_POLICY 将策略添加到策略组
ADD_POLICY_CONTEXT 添加当前应用程序的上下文
DELETE_POLICY_GROUP 删除策略组
DROP_GROUPED_POLICY 从策略组中删除一个策略
DROP_POLICY_CONTEXT 删除活动应用程序的上下文
ENABLE_GROUPED_POLICY 启用或禁用组策略
DISABLE_GROUPED_POLICY 禁用组策略
REFRESH_GROUPED_POLICY 重新解析与策略组关联的、缓存的所有语句
最常用的是 add_policy, drop_policy, create_policy_group, add_grouped_policy.
add_policy的参数:
object_schema IN varchar2 null,
object_name IN varchar2,
policy_name IN varchar2,
function_schema IN varchar2 null,
policy_function IN varchar2,
statement_types IN varchar2 null,
update_check IN boolean false,
enable IN boolean true,
static_policy IN boolean false,
policy_type IN binary_integer null,
long_predicate IN in Boolean false,
sec_relevant_cols IN varchar2,
sec_relevant_cols_opt IN binary_integer null
如果想要用策略控制DML访问表或视图的某些列,则可以设置sec_relevant_cols 这个参数的值(Oracle 10g的新增内容),默认时就是整个表或视图都是控制范围。
VPD差错控制/调试
在VPD策略执行的时候,最常见的错误是"ORA-28113: policy predicate has error","ORA-00936: missing expression"。很多时候都是因为策略函数的返回语句拼接在原DML上面的错误,所以能看到完整的语句就可以很快的找到原因。
方法:使用动态性能视图V$SQLAREA和V$VPD_POLICY。V$SQLAREA包含当前位于共享池中的SQL语句,以及当前的执行统计。视图V$VPD_POLICY列出当前在数据库中实施的所有策略,以及谓词。例如:
select s.sql_text, v.object_name, v.policy, v.predicate
from v$sqlarea s, v$vpd_policy v
where s.hash_value = v.sql_hash;
如果在此查询中添加一个到V$SESSION的连接,则可以识别哪个用户正在运行SQL。该方法的不足之处在于:如果数据库非常忙,则在有机会运行该查询之前,可能由于其他的SQL命令而在共享池中刷新了当前SQL命令。