VPD :Virtual Private Database , 是一种限制对数据库信息细粒度的访问控制技术。实现的关键在于:RLS(Row Level Security) 行级权限控制,通过 ORACLE 的 存储过程:dbms_rls.add_policy 实现.
实现原理:
查询时在 WHERE 语句后 加上 'AND ...', 该功能由策略函数实现。
下面用PL/SQL 简单举例演示。
-- 创建测试表 CREATE TABLE T(organization_id NUMBER,organization_code VARCHAR2(3), organization_name VARCHAR2(150));
-- 插入测试数据 INSERT INTO T VALUES (101,'AAA','name1'); INSERT INTO T VALUES (102,'BBB','name2'); INSERT INTO T VALUES (103,'CCC','name3'); INSERT INTO T VALUES (104,'DDD','name4');
-- 查询所有数据 SELECT * FROM T;
实现如下访问控制:
拒绝访问 organization_id = 101 的行.
-- step 1: 创建查询策略函数 CREATE OR REPLACE FUNCTION f_limited_query_t (s_schema IN VARCHAR2, s_object IN VARCHAR2) RETURN VARCHAR2 AS BEGIN RETURN 'organization_id not in(101)'; END;
-- PS:该函数必须有两个 VARCHAR2 参数,不能去掉,否则报错:ORA-28112: failed to execute policy function
-- step 2: 为对象添加查询策略 BEGIN DBMS_RLS.add_policy (object_schema => 'APPS', object_name => 'T', policy_name => 'POLICY_LIMITED_QUERY_T', function_schema => 'APPS', policy_function => 'F_LIMITED_QUERY_T'); -- 可以使 package.function END;
-- step 3: 测试 SELECT * FROM T;
-- 结果:不能访问到 organization_id = 101 的行. 说明访问策略生效
-- step 4:解除访问控制 BEGIN DBMS_RLS.drop_policy (object_schema => 'APPS', object_name => 'T', policy_name => 'POLICY_LIMITED_QUERY_T'); END;
-------------------我是分割线--------------------------
add_policy 部分字段解释:
dbms_rls.add_policy(object_schema -- object schema ,object_name -- object name ,policy_name -- policy 名, 自己命名 ,function_schema -- function schema ,policy_function -- 策略函数 ,statement_types -- 要使用该 policy 的 DML 类型,如'select,insert,update,delete' ,update_check -- 仅适用于statement_type为'insert,update',值为'true'或'false' ,enable -- 是否启用,值为'true'或'false' );
-- 设置 policy dbms_rls.enable_policy(object_schema -- object schema ,object_name -- object name ,policy_name -- 要删除的policy名称 ,enable -- 是否启用,值为'true'或'false' );
-- 通过 VPD 进行 OU 屏蔽 BEGIN dbms_rls.add_policy(object_name => 'CIB_TABLE', policy_name => 'ORG_SEC', policy_function => 'MO_GLOBAL.ORG_SECURITY', policy_type => dbms_rls.shared_context_sensitive); END;
-- 查看系统中的 policy SELECT * FROM user_policies
使用案例:
为不带ALL的APPS下的同义词添加策略函数: BEGIN dbms_rls.drop_policy(object_schema => 'APPS', object_name => 'CUX_CM_COMMISSION_DTLS', policy_name => 'ORG_SEC'); END; BEGIN dbms_rls.add_policy(object_name => 'CUX_CM_COMMISSION_DTLS', policy_name => 'ORG_SEC', policy_function => 'MO_GLOBAL.ORG_SECURITY'); END;