本文是采用Oracle VPD技术解决同一个OU下按照不同办事处屏蔽销售订单的解决方案。
VPD技术提供了数据库对象(表,同义词,视图)行级别访问的控制。关于VPD更多的信息不在此进行描述,可以查看Oracle Database Security Guide中的Using Virtual Private Database to Implement Application Security Policies章节。
一,业务需求
二,功能需求
由于上面的业务需求,以致需要有下面的功能需求
三,技术方案
一般情况下,这样的需求在Oracle EBS二次开发中都会被认为是“不合理”的需求,如果顾问最终答应了这样的需求,对于开发人员首先会想到的就是修改相关的Form界面以及一些数据库视图的定义,但在Oracle EBS的二次开发规范中,最重要的一条原则就是不能修改标准功能的程序;而在这个案例中,即使我们修改了一些表面上的功能,如销售订单界面,客户信息查询等等,但是很有可能很多标准的报表或者程序都是没有进行相关屏蔽的,这样对于这项开发来说就是一个不可能完成的任务,也是一个风险非常大,以至于留下很多陷阱的开发。
这时候我想到要是有一个办法,能够从基表动态添加一个条件,将其按照办事处进行条件的筛选,那岂不是“釜底抽薪”,彻底解决了我的问题?
VPD通过安全策略(Policy)来动态返回一个条件(WHERE子句)来使得从行级别进行数据的屏蔽,将一个或多个安全策略与表或视图关联后,就实现了Oracle数据库的VPD功能。对带安全策略的表进行直接或间接访问时,数据库将调用一个实施该策略的函数,策略函数返回一个访问的条件(WHERE 子句),即谓词。应用程序将它附加到用户的 SQL 语句后面,从而动态修改用户的数据访问权限。
一般情况下,开发人员通过编写一个存储过程将 SQL 谓词附加到每个 SQL 语句(用于控制该语句的行级别访问权限)来实现VPD。VPD确保了无论用户以何种方式访问数据(通过应用程序、报表编写工具或SQL*Plus),都将强制实施访问权限控制策略,所以如果开发人员对oe_order_headers_all添加了一个“header_id > 1000 ”的条件谓词,那当任何程序以select * from oe_order_headers_all进行数据访问的时候,实际上真正运行的SQL语句则是select * from oe_order_headers_all WHERE header_id > 1000 ,因此通过动态生成WHERE谓词条件从而达到动态控制数据的安全。
下面是技术解决方案的主要步骤:
四,技术实现
很多技术的实现省略了,主要描述VPD策略如何实现:
首先是编写WHERE谓词条件:
FUNCTION oe_order_header_predicate( oowner IN VARCHAR2, ojname IN VARCHAR2) RETURN VARCHAR2 IS l_branch_code VARCHAR2(10); BEGIN -- 得到办事处预制文件的值 l_branch_code := fnd_profile.VALUE('CUX_BRANCH_CODE') -- if the responsibility not set the CUX_BRANCH_CODE profile's value -- and all data are visible; otherwise, the data is restricted to profile IF l_branch_code IS NOT NULL THEN RETURN ('attribute1 = ' || l_branch_code ) ; ELSE RETURN ('1=1'); END IF; END oe_order_header_predicate;
oe_order_header_predicate过程的两个参数类型是固定的,同时本文演示中将它放在cux_vpd_policy数据库包中
下面是注册VPD策略:
BEGIN dbms_rls.add_policy( object_schema => 'apps', object_name => 'oe_order_headers_all', policy_name => 'bsm_oe_order_headers_rls1', function_schema => 'apps', policy_function => 'cux_vpd_policy.oe_order_header_predicate'); END;
上面只是演示了为销售订单头表添加VPD策略
来源:http://oracleseeker.com/2009/04/27/using_vpd_hide_information_in_oracle_ebs/