oracle 策略Policy

浏览: 2426

接触到策略还是因为权限的问题,领导分配任务让给用户分权限,才开始了解策略的使用

数据访问权限控制,绝大部分BI系统都会遇到,简单说一下权限控制(包括数据库及报表层级大体实现逻辑相同都是

通过某些ID来控制)

  在大部份系统中,权限控制主要定义为模块进入权限的控制和数据列访问权限的控制(如:某某人可以进入某个控

制,仓库不充许查看有

关金额的字段等等)。

  但在某些系统中,权限控制又必须定义到数据行访问权限的控制,此需求一般出现在同一系统,不同的相对独立

机构使用的情况。(如:

集团下属多个子公司,所有子公司使用同一套数据表,但不同子公司的数据相对隔离)

  当然,绝大多数人会选择在View加上Where子句来进行数据隔离。此方法编码工作量大、系统适应用户治理体系的

弹性空间较小,一旦权

限逻辑发生变动,就可能需要修改权限体系,导致所有的View都必须修改。

然后就用到oracle的策略了,Oracle策略可以限制查询、修改、删除、新增等操作 

  Policy应用于数据行访问权限控制时,其作用简而言之,就是在查询数据表时,自动在查询结果上加上一个Where

子句。假如该查询已有

where子句,则在该Where子句后面加上"And ..."。

  由Oracle Policy自动加入的Where子句的内容,通常由一个函数来实现。而进行数据行访问权限控制算法实现的

结果,也是通过该函数返回。

    policy的基本语法

begin
-- Call the procedure
sys.dbms_rls.add_policy(object_schema => :数据表(或视图)所在的Schema名称/用户,
object_name => :数据表(或视图)的名称,
policy_name => :policy的名称
function_schema => :返回Where子句的函数所在Schema名称/用户,
policy_function => :返回Where子句的函数名称,
statement_types => :要使用该Policy的DML类型,如'Select,Insert,Update,Delete',
update_check => 仅适用于Statement_Type为'Insert,Update',值为'True'或'False',
enable => 是否启用,值为'True'或'False',
static_policy => 默认值为FALSE。如果它被设置为TRUE则所有用户启用该策略,sys或特权用户例外。
policy_type => :默认值是null,意味着static_policy的值决定,在这里指定任何策略将覆盖static_policy的值。
long_predicate => long_predicate,
sec_relevant_cols => :敏感的字段名称,
sec_relevant_cols_opt => :设置为dbms_rls.ALL_ROWS来显示所有的行,敏感的列的值为null);
end;

介绍一下使用场景:主业务库,也就是所有数据的融合库,其它用户需要从主数据库读数据,按照用户来分配权限。

    实现原理:我们的业务场景是每个用户下还有很多子机构,id是范围id,所以创建了一个中间表来维护所有用户及其id范围,主要字段就是用户名,最小ID,最大ID,然后创建函数根据用户session在中间表匹配出对应的ID范围即可。中间没有涉及到敏感字段问题,只是简单的查询权限控制。

创建函数:

CREATE OR REPLACE FUNCTION F_DATA_QUERY_RULE(OBJECT_SCHEMA IN VARCHAR2, OBJECT_NAME VARCHAR2) RETURN VARCHAR2 IS
--=======================================================
--访问规则
--=======================================================
N_SSDWDM VARCHAR(20) ; --所属单位
N_SSDWDM_MAX VARCHAR(20) ; --子单位最大值
V_USER_CONTEXT VARCHAR(50); --当前用户
V_USER_TABLE VARCHAR(50); --数据库用户
L_PREDICATE VARCHAR2 (200); --拼接条件

BEGIN
--根据SYS_CONTEXT('USERENV','SESSION_USER')获取到用户session然后匹配中间表取出where条件
SELECT UPPER(USER_NAME),
SSDWDM_MIN||'',
SSDWDM_MAX||'',
SYS_CONTEXT('USERENV','SESSION_USER')
INTO V_USER_TABLE, N_SSDWDM, N_SSDWDM_MAX, V_USER_CONTEXT
FROM 维护的中间表
WHERE UPPER(USER_NAME)= SYS_CONTEXT('USERENV','SESSION_USER');
--实现逻辑
IF(TRIM(UPPER(V_USER_CONTEXT))='主数据库的scheme') THEN
L_PREDICATE := '1=1';
ELSE
L_PREDICATE :='SSDWDM BETWEEN ' || '''' || N_SSDWDM || '''' || ' AND ' || '''' ||N_SSDWDM_MAX || '''';
END IF;
RETURN(L_PREDICATE);
END F_DATA_QUERY_RULE;

添加策略:

BEGIN
DBMS_RLS.ADD_POLICY (OBJECT_SCHEMA => 'SCHEME_XXX'
,OBJECT_NAME => 'V_XXX'
,POLICY_NAME => 'POLICY_NAME_XXX'
,FUNCTION_SCHEMA => 'SCHEME_XXX'
,POLICY_FUNCTION => 'F_DATA_QUERY_RULE' --函数名
,STATEMENT_TYPES => 'SELECT' --使用策略的类型
);
END;

授权:

GRANT SELECT ON V_XXXX TO XX;

如果原系统已有相关的策略,则需要先查询一下需要授权的数据表有没有该策略,如果有只需要直接授权即可,查询语句:

SELECT * FROM USER_POLICIES WHERE OBJECT_NAME = 'V_XXX'

删除策略:

--删除策略
DECLARE
BEGIN
DBMS_RLS.DROP_POLICY('SCHEMA_USER', --要删除的POLICY所在的SCHEMA
'TABLE_NAME', --要删除POLICY的数据表(或视图)名称
'POLICY_NAME' --要删除的POLICY名称
);
END;

看到这个oracle Policy的应用--DBMS_RLS.ADD_POLICY里用到了敏感字段的例子,拿来有兴趣的可以看看。


关于敏感字段问题,如何使用多个敏感字的:

begin  
dbms_rls.add_policy(object_schema => 'SYSTEM'
,object_name => 'EMP_SYS'
,policy_name => 'emp_policy'
,function_schema => 'SYSTEM'
,policy_function => 'FN'
,sec_relevant_cols => 'sal,ename' --此处直接在单引号里添加即可
,sec_relevant_cols_opt => dbms_rls.ALL_ROWS);
end;
推荐 0
本文由 KGdom 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册