前言
数据访问权限控制是一个古老而又实际的问题
在大部份系统中权限控制主要定义为模块进入权限的控制和数据列访问权限的控制(如某某人可以进入某个控制仓库不充许查看有关金额的字段等等)
但在某些系统中权限控制又必须定义到数据行访问权限的控制此需求一般出现在同一系统不同的相对独立机构使用的情况(如集团下属多个子公司所有子公司使用同一套数据表但不同子公司的数据相对隔离)
当然绝大多数人会选择在View加上Where子句来进行数据隔离此方法编码工作量大系统适应用户管理体系的弹性空间较小一旦权限逻辑发生变动就可能需要修改权限体系导致所有的View都必须修改
本文探讨的使用Oracle提供的Policy管理方法来实现数据行的隔离
特别感谢Javac兄提出的此解决方案!
实现
Oracle Policy的简单说明
Policy应用于数据行访问权限控制时其作用简而言之就是在查询数据表时自动在查询结果上加上一个Where子句如果该查询已有where子句则在该Where子句后面加上And
由Oracle Policy自动加入的Where子句的内容通常由一个函数来实现而进行数据行访问权限控制算法实现的结果也是通过该函数返回
Oracle Policy的语法简述
新增Policy
Dbms_RlsAdd_Policy(Object_Schema 数据表(或视图)所在的Schema名称
Object_Name 数据表(或视图)的名称
Policy_Name POLICY的名称主要用于将来对Policy的管理
Function_Schema 返回Where子句的函数所在Schema名称
Policy_Function 返回Where子句的函数名称
Statement_Types 要使用该Policy的DML类型如SelectInsertUpdateDelete
Update_Check 仅适用于Statement_Type为InsertUpdate值为True或False
Enable 是否启用值为True或False
);
注如果Update_Check设为True则用户插入的值不符合Policy_Function返回条件时该DML执行返回错误信息
删除Policy
Dbms_Rlsdrop_policy(object_schema 要删除的Policy所在的Schema
object_name 要删除Policy的数据表(或视图)名称
policy_name 要删除的Policy名称
);
设定Policy状态
Dbms_RlsEnable_Policy(object_schema 要删除的Policy所在的Schema
object_name 要删除Policy的数据表(或视图)名称
policy_name 要删除的Policy名称
Enable 是否启用值为True或False
);
Policy使用特性及使用建议
● 一个数据表(或视图)可以有多个Policy但Policy的名称在整个Schema范围内不允许重复
● 如果将Policy指定到视图则删除Policy后应重新编译该视图否则User_Updatable_Columns系统字典表返回的是否可新增修改删除的信息可能会全部为NOT
● 通过Policy可以限制用户对数据表记录的操作范围如果Policy加在数据表则由于前台涉及的数据源(通常是视图)往往涉及许多张数据表权限控制难度很大建议将Policy加在视图
Oracle Policy 应用实例
创建测试数据表
Create Table T_Policy(T Varchar()T Number());
创建测试的Policy函数
CREATE OR REPLACE Function Fn_GetPolicy (P_Schema In Varchar
P_Object In Varchar)
Return Varchar
Is
Begin
Return T=;
End;
插入测试数据
Insert Into T_Policy Values(a);
Insert Into T_Policy Values(b);
Insert Into T_Policy Values(c);
Commit;
加入Policy
Begin
Dbms_RlsAdd_Policy(Object_Schema =>Scott
Object_Name =>T_Policy
Policy_Name =>T_TestPolicy
Function_Schema =>Scott
Policy_Function =>Fn_GetPolicy
Statement_Types =>SelectInsertUpdateDelete
Update_Check =>True
Enable =>True
);
End;
测试Policy
Select * From T_Policy;
Insert Into T_Policy Values (d);
Insert Into T_Policy Values (d);
Commit;
查看Policyy设定情况
Select * From user_policies;
重要提示执行Dbms_RlsAdd_Policy时必须将执行Dbms_Rls包执行的权限授予Scott测试时也可能使用其它Schema最简单的方法是将测试的Schame设为DBA权限