ITPub博客

首页 > Linux操作系统 > Linux操作系统 > MOAC应用包: MO_GLOBAL解析

MOAC应用包: MO_GLOBAL解析

原创 Linux操作系统 作者:静夜细藤 时间:2011-07-28 16:09:09 0 删除 编辑

转---王浩鑫 EBS R12 MOAC原理探索


MOAC总体流程概述
对多OU访问技术,11i与R12的区别:
r12:利用virtual private database (VPD)技术为数据库表添加MO_GLOBAL.ORG_SECURITY安全性检测方法。可以通过查询表DBA_POLICIES查看表上的约束。
11i:利用基于各个模块基表的多OU视图实现多OU控制。

  1. 该方法正是对OU安全性控制的方法,在该方法对多OU情况下org_id判断的过程中,查询了一张非常重要的表po_glob_org_access_tmp,而对单OU访问模式下是判断当前org_id和context的org_id是否相同。po_glob_org_access_tmp表是一张session临时表,它存放着当前的用户访问中有权限访问的所有OU信息。
  2. 通过上面的概述,我们可以提取出四个关键词VPDORG_SECURITY,MO_GLOBAL ,CONTEXT,PO_GLOB_ORG_ACCESS_TMP,整个MOAC的实现过程呢可以看作是对这几个关键词的串联理解,首先是向PO_GLOB_ORG_ACCESS_TMP插入当前能操作的ORG_ID,然后是通过MO_GLOBAL的一系列方法设置CONTEXT的值(包括访问模式和当前org_id),最后是使用VPD向相对应的同义词上添加ORG_SECURITY验证,当访问模式为Single-org时,对当前的org_id使用CONTEXT值进行验证,当访问模式为Mutil-org,对当前的org_id使用表 po_glob_org_access_tmp验证,通过验证的数据即为安全操作数据。重点会涉及到VPD的实现,以及对po_glob_org_access_tmp表的分析和对MO_GLOBAL分析理解。
  3. po_glob_org_access_tmp表的分析2.2.1.
    po_glob_org_access_tmp介绍:
    在多OU的实现中,VPD都是通过判断基表的org_id是否在po_glob_org_access_tmp表中存在,如果存在则为安全数据。该表是一张session临时表,其中的值只能通过使用mo_globlal和mo_utils包的方法进行操作。该表中的值是在mo_global.populate_orgs中进行插值,mo_global.delete_orgs进行删除操作的,在populate_orgs过程中,有这样一条bug修改记录:
    Bug fix 4511279:Need to populate temp table even when access mode is "S".
    该注释表明,该表不仅在多OU模式下需要插值,并且在单OU模式下也需要进行插值操作,当然单OU下该表有且仅有一条记录。
    mo_global.populate_orgs方法包含四个参数:
    PROCEDURE populate_orgs (
    p_org_id_char
    VARCHAR2,
    p_sp_id_char
    VARCHAR2,
    p_current_org_id
    OUT NOCOPY VARCHAR2,
    p_view_all_org
    OUT NOCOPY VARCHAR2);
    p_org_id_char和p_sp_id_char 的值分别对应“MO: Operating Unit”和MO: Security Profile”预制文件的值,在调用populate_orgs过程前,有一个逻辑判断
    IF l_security_profile_id IS NOT NULL THEN
    l_org_id := null;
    END IF;
    该逻辑的含义即为,如果设置了“MO: Security Profile”预制文件,那么MO: Operating Unit”的值会自动被覆盖,也即是参数p_org_id_char和p_sp_id_char中一定是有一个为空的。当p_org_id_char不为空时,肯定是单OU模式。

p_org_id_char
当前的OU “MO: Operating Unit

p_sp_id_char

当前的安全性配置文件“MO: Security Profile

p_current_org_id

当前的org_id

p_view_all_org

是否查看所有的OU标示

  1. table记录的生成逻辑:
    在多OU的设置开始我们会定义一个安全性配置文件和设置当前的安全性配置文件,该配置文件中定义了一系列组织访问的权限控制,我们可以使用下面语句查询出当前使用的安全性控制文件
    SELECT security_profile_name
    , business_group_id
    ,view_all_organizations_flag

    FROM per_security_profiles


    WHERE security_profile_id =


    to_number(fnd_profile.VALUE('XLA_MO_SECURITY_PROFILE_LEVEL'));

    [url=mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht!][img=500,29]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img][/url]

    可以通过以下语句获取当前安全性配置文件和当前用户在当前职责下可访问的OU
    SELECT per.organization_id
    organization_id

    , hr.NAME
    name


    FROM
    per_organization_list per

    , hr_operating_units hr

    WHERE per.security_profile_id = to_number(fnd_profile.VALUE('XLA_MO_SECURITY_PROFILE_LEVEL'))

    AND hr.organization_id = per.organization_id
    AND hr.usable_flag is null;

    [url=mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht!][img=276,95]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img][/url]
    当一切条件设置完成后,下面进入mo_global.populate_orgs进行插值操作,伪代码如下:


    1 IF
    安全性配置文件预制文件不为空
    THEN

    获取安全性预制文件的信息,文件名,业务组,查看所有标示
    SELECT security_profile_name
    , business_group_id,
    view_all_organizations_flag

    INTO
    l_sp_name

    ,l_bg_id
    ,p_view_all_org
    FROM per_security_profiles
    WHERE security_profile_id = to_number(p_sp_id_char);


    1.1 IF
    安全性配置文件没有设置组织控制 THEN

    1.1.1 IF
    安全性预制文件指定了业务组 THEN

    获取该业务组下对应的所有org_id
    SELECT hr.organization_id
    organization_id

    ,hr.name
    NAME

    INTO

    t_org_id

    ,t_ou_name;
    FROM
    hr_operating_units hr

    WHERE hr.business_group_id = l_bg_id
    AND hr.usable_flag is null;


    1.1.2 ELSE
    安全性预制文件没有定业务组 THEN

    获取系统所有的org_id
    SELECT hr.organization_id organization_id
    ,hr.NAME
    NAME

    INTO
    t_org_id

    ,t_ou_name;
    FROM hr_operating_units hr
    WHERE hr.usable_flag IS NULL;

    END IF;


    1.2 ELSE 安全性设置文件中指定了OU范围 THEN
    获取安全性配置文件对应的所有Org_id
    SELECT per.organization_id organization_id
    ,hr.NAME
    NAME
    INTO
    t_org_id
    ,t_ou_name;
    FROM per_organization_list per, hr_operating_units hr
    WHERE
    per.security_profile_id = to_number(p_sp_id_char)
    AND
    hr.organization_id = per.organization_id
    AND
    hr.usable_flag IS NULL;
    END IF;


    2
    ELSE
    没有设置安全性配置文件 THEN

    2.1 IF 当前OU配置文件有值 THEN

    获取当前的org_id

    SELECT hr.organization_id
    organization_id

    , hr.name
    NAME

    INTO t_org_id
    ,t_ou_name;
    FROM hr_operating_units hr
    WHERE hr.organization_id = to_number(p_org_id_char)
    AND hr.usable_flag is null;
    END IF;
    END IF;


    3 IF
    如果t_org_id的长度大于1,即为当前用户有多OU访问权限 THEN

    获取用户首选项的org_id的值
    SELECT organization_id
    FROM fnd_mo_sp_preferences
    INTO t_pref_org_id
    WHERE user_id = fnd_global.user_id
    AND resp_id = fnd_global.resp_id;


    3.1 IF
    用户首选项的t_pref_org_id表长度不为空 then
    3.1.1 IF (g_sync <> 'N') THEN
    sync_ind := 'Y';
    END IF;
    判断用户首选项的值和当前所有的OU值是否相同,如果相同
    则将值放入放入t_common_org信息表中;
    将fnd_mo_sp_preferences用户首选项表中没有访问权限的OU信息删除

    END IF;


    3.2
    IF

    要求同步 (sync_ind = 'Y') AND 首选项中有值 THEN
    FOR i IN t_common_org_id.FIRST .. t_common_org_id.LAST LOOP
    INSERT
    INTO mo_glob_org_access_tmp
    (organization_id
    ,
    organization_name)

    VALUES (t_common_org_id(i)
    ,
    t_common_ou_name(i));

    END LOOP;


    3.3 ELSIF
    如果没有要求同步,则mo_glob_org_access_tmp表中
    的值为当前能选择的所有值 then
    FOR i IN t_org_id.FIRST .. t_org_id.LAST LOOP
    INSERT
    INTO mo_glob_org_access_tmp
    (organization_id
    ,
    organization_name)

    VALUES (t_org_id(i)
    ,
    t_ou_name(i));

    END LOOP;
    END IF;


    g_ou_count := t_org_id.COUNT;


    END IF;


    4
    IF p_sp_id_char IS NOT NULL AND l_bg_id IS NOT NULL AND 访问所有OU标示 = 'Y' THEN
    设置访问所有OU的标志
    访问所有OU标示 := 'N';
    END IF;


    设置全局访问模式
    5 IF
    访问所有OU标示 = 'Y' THEN
    访问模式:='A'; --ALL


    6 ELSIF g_ou_count = 1 THEN
    访问模式:='S'; --Single


    7 ELSIF g_ou_count > 1
    THEN
    访问模式:='M'; --Mutil

    END
    IF;


    8 IF ou表的长度=1 THEN
    设置默认org_id为当前唯一的org_id
    END IF;


    2.2.3.view_all_organizations_flag字段
    在上段的分析过程中,有一个概念是
    访问所有OU标示(p_view_all_org)它是对应的安全性配置文件表的view_all_organizations_flag字段,当界面上的安全性类型为查看所有组织(无安全性)时,此值对应的结果为“Y”,否则为“N”。

    [img=300,202]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
    2.2.4.fnd_mo_sp_preferences值逻辑
    在上面的分析过程中涉及到一个fnd_mo_sp_preferences表,在多OU操作的情况下,向po_glob_org_access_tmp表插值时需要检查设置fnd_mo_sp_preferences的值,只有是该表和查询出的结果值都满足才插入到po_glob_org_access_tmp,他的设置是在1.2.6中介绍的。
    按照1.2.6的界面查询值是只有一个默认值的结果的,但当我们将四个组织都设置为首选时如图

    [img=300,191]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
    该查询才会有值
    SELECT msp.user_id
    ,msp.resp_id
    ,msp.security_profile_id
    ,msp.organization_id
    FROM fnd_mo_sp_preferences msp;
    结果如下:

    [img=300,58]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
    security_profile_id=0的记录是怎么产生的呢? 通过查询
    SELECT security_profile_name
    ,business_group_id
    ,view_all_organizations_flag
    FROM per_security_profiles
    WHERE security_profile_id = 0

    [img=300,25]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
    可以得知该值时安全性配置文件Setup Business Group产生的,该文件时系统默认的安全性配置文件。其内部机制有待研究……


    2.2.5.
    总结
    在该节中对po_glob_org_access_tmp的值生成分析是对应的多OU模式下的验证值,但在进行验证的过程中有段代码是:

    EXISTS (SELECT 1

    FROM mo_glob_org_access_tmp oa
    WHERE oa.organization_id = org_id)
    但对应单OU模式下的验证语句
    org_id = sys_context(''multi_org2'',''current_org_id'')
    sys_context(''multi_org2'',''current_org_id'')的值是怎么获取的呢?在下面的2.3节将会对其进行讨论,同时我们经常所说的访问模式是指什么,它的生成逻辑和控制方式又是怎样的呢?这也将会在2.3节进行讨论。


    2.3.
    MO_GLOBAL包的分析2.3.1.
    概述
    在2.1的过程概述中提到的流程概述中,整个流程的核心都是在MO_GLOBAL中完成的,包括对po_glob_org_access_tmp记录的插入,访问模式的设置,默认OU的获取,对VPD的支持(提供ORG_SECURITY验证方法),在该节将会对这些概念进行理解,在此基础上对MO_global
    pakage进行分析。
    2.3.2.
    访问模式(Access Mode)
    在MOAC的实现中,采用Access Mode来控制当前是Mutil org还是Single org。常见的有三种模式:

S

Single
单OU模式

M

Mutil
多OU模式

A

All
预留将来使用

X



阻止从同义词返回任何数据

值的产生逻辑:
访问模式值生成逻辑是在mo_global.set_org_access中实现的,它有三个参数

p_org_id_char

The operating unit ID for the current session

p_sp_id_char

The security profile id for the current session

p_appl_short_name

Application owner for the current module or session

PROCEDURE set_org_access(p_org_id_char
VARCHAR2,

p_sp_id_char
VARCHAR2,

p_appl_short_name VARCHAR2)
该方法中调用了populate_orgs和set_org_context方法,其中populate_orgs的作用和逻辑在2.2中已经阐述,但该方法中需要使用到populate_orgs中设置的一些全局变量和一些返回值。set_org_context方法主要是对Access Mode进行付值。


该方法的伪代码:




1 IF 当前的数据库实例不是multi-org数据库实例 THEN
RETURN;

END IF;

2 IF "MO: Security Profile"预制文件和"MO: Operating Unit"预制文件都没有设置 THEN
抛出异常
3 ELSIF 应用简称为空 THEN
抛出异常
END IF;

4
获取当前应用是否支持Mutil-org的标示
SELECT nvl(mpi.status, 'N')
INTO l_access_ctrl_enabled
FROM fnd_mo_product_init mpi
WHERE mpi.application_short_name = p_appl_short_name;
5 删除表po_glob_org_access_tmp中的数据

delete_orgs;

6 IF 支持Mutil-org THEN
6.1 IF 当前环境设置了安全性配置文件 THEN
"MO: Operating Unit"值被覆盖;
END IF;

6.2 populate_orgs(l_org_id,
l_security_profile_id,
l_current_org_id,
l_view_all_orgs);
判断当前是否有多个OU
6.3 IF OU个数为0 THEN
RAISE NO_ORG_ACCESS_FOUND;
6.4 ELSIF OU个数为1 THEN
设置Access MODE为'S',且org_id为当前唯一的org_id
set_policy_context('S', l_current_org_id);
6.5 ELSE OU个数>1 THEN

6.5.1 IF
访问所有OU标示= 'Y' THEN
设置Access MODE为'A'
set_policy_context('A','');
6.5.2 ELSE
设置Access MODE为'M'
set_policy_context('M','');
END IF;
END IF;
7 ELSE 当前应用不支持多OU
7.1 IF 已经设置了"MO: Operating Unit"预制文件 THEN


7.1.1 populate_orgs(l_org_id,

null,

l_current_org_id,

l_view_all_orgs);
7.2
设置Access MODE为'S',且org_id为预制文件的Org_id
set_policy_context('S',l_org_id);
END IF;
END IF;
8 commit;


在该方法中共产生了三种访问模式,但这些访问模式是怎样付值和被VPD所使用的呢?这就需要另一个知识点
Application context……

2.3.3.应用程序上下文(Application context)的理解
介绍:应用程序上下文,其实就是个环境变量,在SESSION的生命周期内有效。oracle官方的资料如下:
Application context can be useful for the following purposes:
1.Enforcing fine-grained access control
2.Preserving user identity across multitier environments
3.Serving as a secure data cache for attributes needed by an application for fine-grained auditing or for use in PL/SQL conditional statements or loops
This cache saves the repeated overhead of querying the database each time such attributes are needed.
4.Serving as a holding area for attribute-value pairs that an application can define, modify, and access
Three types of application context are defined, differentiated by where the context data is stored and by how updates can be done:
1.Secure session-based application contexts, for which data is stored in the database user session (UGA) in a namespace specified by an SQL command (CREATE CONTEXT).
2.The client session-based application context, using only the CLIENTCONTEXT namespace, updatable by any OCI client or by the existing DBMS_SESSION API for application context. No privilege or package security check is done.
3.Nonsession-based (global) application contexts, for which data is stored in the shared area (SGA).


创建语法:
CREATE CONTEXT cux_context_name USING apps.cux_vpd_global
cux_context_name 是应用程序上下文的名称(namespace)
apps.cux_vpd_global是可以对这个namespace进行变量的创建和删除的package
相关DB对象:
dba_context,sys.context$ c,
sys.obj$



在MOAC中的使用:
在MOAC中我们是用的是第二种类型的client session-based应用上下文
付值:使用DBMS_SESSION. set_context方法操作
procedure set_context(namespace varchar2,
attribute varchar2, value varchar2,
username varchar2 default null,
client_id varchar2 default null);

namespace

Name of the namespace to use for the application context

attribute

Name of the attribute to be set

value

Value to be set

Egdbms_session.set_context('multi_org', 'access_mode', p_access_mode);
取值:使用sys_context(namespace, attribute)
Egsys_context('multi_org2','current_org_id')
为了获取在MO_GLOBAL中使用的context,可以根据定义使用语句:
SELECT *

FROM dba_context dc


WHERE package = 'MO_GLOBAL'


在MO_GLOBAL中对这两个值的使用在mo_global.set_policy_context方法中

multi_org
access_mode属性存放的是当前的访问模式.
multi_org2current_org_id属性存放的是当前的org_id.
两参数的信息:

multi_org

access_mode
S=Single, M=Multiple, A=All, X=None

multi_org2

current_org_id
Operating unit org id, only applicable if access mode is Single



其中access_mode和current_org_id的值在mo_global.set_org_access方法中已经获取到了,但access_mode=’A’或’M’时current_org_id为空,否则current_org_id值为当前的唯一Org_id;经过上面一系列的讨论,可以得到mo_global.set_policy_context的付值是多OU产生阶段的最后一个步骤,接下来我们解析一下这个逻辑,



mo_global.set_policy_context
伪代码:
1 IF 当前的access_mode和org_id未发生改变 THEN
返回(状态没有变,不需要设置);
2 ELSIF 参数access_mode='S' THEN
2.1
IF 当前的access_mode为空 or
当前的access_mode<>'S' THEN
-设置access_mode Context的值

dbms_session.set_context('multi_org', 'access_mode', p_access_mode);
g_access_mode := p_access_mode;
END IF;
2.2 IF (当前的org_id为空 or
当前的org_id<>参数org_id or
上下文中的org_id <> 参数org_id
-- Bug4916086
OR
上下文中的org_id为空) THEN
设置current_org_id context的值
dbms_session.set_context('multi_org2', 'current_org_id', p_org_id);
g_current_org_id := p_org_id;
END IF;


3 ELSIF (参数access_mode = 'M') THEN
3.1 IF 当前的access_mode为空 or
当前的access_mode<>'M' THEN
--设置access_mode Context的值

dbms_session.set_context('multi_org', 'access_mode', p_access_mode);
g_access_mode := p_access_mode;
END IF;
3.2 IF (当前的org_id不为空 ) THEN
将current_org_id Context的值清空
dbms_session.set_context('multi_org2', 'current_org_id', '');
g_current_org_id := NULL;
END IF;


4 ELSIF (参数access_mode = 'A') and g_init_access_mode = 'A' THEN
4.1 IF 当前的access_mode为空 or
当前的access_mode<>'A' THEN
-设置access_mode Context的值

dbms_session.set_context('multi_org', 'access_mode', p_access_mode);
g_access_mode := p_access_mode;
END IF;
4.2 IF (当前的org_id不为空 ) THEN
将current_org_id Context的值清空
dbms_session.set_context('multi_org2', 'current_org_id', '');
g_current_org_id := NULL;
END IF;


5 ELSIF (参数access_mode in ('X','B')) THEN
5.2 IF 上下文中的org_id is not null then
将current_org_id Context的值清空
dbms_session.set_context('multi_org2', 'current_org_id', '');
end if;
设置access_mode CONTEXT的值
dbms_session.set_context('multi_org', 'access_mode', p_access_mode);
g_current_org_id := NULL;
g_access_mode := p_access_mode;


6 ELSIF (参数access_mode为空) THEN
6.1 IF (g_access_mode IS NOT NULL) THEN
设置access_mode CONTEXT的值
dbms_session.set_context('multi_org', 'access_mode', p_access_mode);
g_access_mode := p_access_mode;
END IF;
6.2 IF (当前org_id不为空) THEN
将current_org_id Context的值清空
dbms_session.set_context('multi_org2', 'current_org_id', '');
g_current_org_id := NULL;
END IF;
END IF;



7

获取当前用户和职责的信息,用以验证MO设置是否完成

g_old_user_id:=sys_context('FND','USER_ID');


g_old_resp_id:=sys_context('FND','RESP_ID');

2.3.4.
mo_global 流程理解
到了这一步,我们已经分别将值放到了po_glob_org_access_tmp和context中,但是系统是怎么实现这个功能的呢?它的出发点在什么地方呢,在oracle ETRM上查询引用在这个包的数据库对象,有706个,真正使用mo_global.unit的入口包是哪个,我不能确定,但我们只要理解它从mo_global.unit这个口进入后的流程也就能理解了MOACOrg_id安全机制了。
mo_global主要流程图
[img=300,202]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]

该流程图展示了系统设置Organization Security Policy的整个流程,通过该流程,系统将MO的Org_id放入session 临时表po_glob_org_access_tmp表中,将Access mode值存储到Application context multi_orgaccess_mode attribute中,将当前默认的org_id存入到Application context multi_org2current_org_idattribute中,我们可以在程序中使用
sys_context('multi_org2','current_org_id') 获取当前的org_id,使用sys_context('multi_org', 'access_mode')获取当前的访问模式。
这两个值是我们多OU访问判断的关键,在2.4中会阐述怎么使用这两个值进行多OU的安全性策略控制。
2.3.5.总结
在这一节中讨论到MO_GLOBAL包在生成MO的OU信息,同时理解了Access mode 和application context这两个概念,但我们只是涉及到了对MO的设置,并没有解决1.1.3中的同义词没有值的问题,我们也知道了需要使用我们设置的Access mode 和application context,但系统到底是怎使用的呢?在使用这两个值的过程中需要引入新的概念VPD……
2.4.
VPD介绍和使用实例2.4.1.
VPD介绍
什么是VPD(虚拟专用数据库)
VPD
is one feature that allows development community to enforce security by attaching a security policy to database objects such as tables, views and synonyms.

简单的说,VPD就是向特定的数据库对象附加一个安全策略,在对这个对象操作的过程在中,会自动的使用这个安全策略进行验证,同时满足自定义条件和安全策略的操作才会获得预期的结果。下面以一个故事来介绍VPD
在一个交友网站上,有一张表ALL_PERSON_INFO存放该网站所有帅哥靓女的信息,该表有一个字段gender来存放该记录的性别。当一个用户登录该网站时,系统会有一个session值记录当前用户的性别。同时为了防止该网站背上同性恋之家的黑名,于是站长就来了一条严重的限制,该网站的用户只能查看到异性的信息。当一位名叫Tea的帅哥登录到这个网站,需要查找名字中带有coffee的女性时,常有的查询语句是:
Select * from
ALL_PERSON_INFO
api

where
api. Gender <>session( ‘gender’)

and api.name like = ‘%coffee%’
很好,该语句查到的永远都是用户的异性信息。

但一个电脑牛人gay却想去看该系统的帅哥信息,他获取到这条查询语句后,使用SQL注入的技术(或其他技术)在该SQL查询上添加了另外一个条件,然后变成如下语句:
Select * from
ALL_PERSON_INFO
api

where
api. Gender <>session( ‘gender’)

and api.name like = ‘%coffee%’
or api. Gender = session( ‘gender’)
这样造成的结果就是该网站所有的帅哥信息,赤裸裸地被这个gay拿去和他的同类们分享。
于是该网站的站长就气愤地找他们的DBA,说他没有把数据保护好,这下可苦了这个DBA,但却是也不是他的错啊,话虽如此,但系统优化还是得继续。这个DBA开始了他的优化系统之路,通过多方查找,他将视线定位在了VPD上,使用该技术,他成功根除了这个安全隐患。他的基本步骤概括如下:
首先将session( ‘gender’)放到一个APPLICATION CONTEXT中,然后为该表建立了一个同义词GENDER_PERSON_INFO,然后在该同义词上设置了一项安全策略,该策略具有一个相关函数,称为policy function,它返回一个用作谓词的字符串api. Gender <>sys_context(‘friend’,’gender’),通过使用该策略,凡是含有api. Gender = session( ‘gender’)的查询将不会返回任何结果。
接下来来一个VPD使用的实例……
2.4.2.
VPD使用实例


a. 建立对象和数据
CREATE TABLE hss.vpd_test(

ID NUMBER,


NAME VARCHAR2(100),


gender CHAR(1)

);


INSERT INTO hss.vpd_test VALUES(1,'hansen','M');
INSERT INTO hss.vpd_test VALUES(2,'tea','M');
INSERT INTO hss.vpd_test VALUES(3,'tiger','F');
INSERT INTO hss.vpd_test VALUES(4,'coffee','F');
COMMIT;
查询数据如下:
[img=300,154]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]

b. 在APPS下建立同义词
CREATE SYNONYM HX_VPD_TEST For hss.vpd_test;
查询结果如下

[img=300,118]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
c. 建立应用程序上下文
CREATE CONTEXT HX_VPD USING apps.XXHX_VPD_PKG;
查询结果如下

[img=300,91]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
d. 建立策略函数包和应用设置函数包,包头定义如下,包体见附录
CREATE OR REPLACE PACKAGE XXHX_VPD_PKG IS

/*==================================================

Program Name:


XXHX_VPD_PKG


Description:


该pakcage的功能是建立策略函数gender_valid

设置应用程序上下文值



History:


1.00
2008-11-28
hansen
Creation


==================================================*/




/*==================================================

Function Name :


gender_valid


Description:


安全策略函数必须带2个参数:第1个参数是方案名

(或用户名)、第2个参数是方案对象名(或表名、

视图名)。该函数返回附加到SQL语句的where子句

后面的字符串.即使在安全策略函数中不使用也要带

上所述2个参数,否则在执行时会出现“ORA-28112:

无法执行策略函数”的错误提示。

Argument:


obj_schame
方案名

obj_name
方案对象名

Return


安全策略字符串

History:


1.00
2008-11-28
hansen
Creation


==================================================*/




FUNCTION gender_valid(obj_schame VARCHAR2,

obj_name
VARCHAR2) RETURN VARCHAR2;



/*==================================================

Function Name :


set_context


Description:


该方法用于设置应用程序上下文的值

Argument:



p_user_gender
性别


History:


1.00
2008-11-28
hansen
Creation


==================================================*/



PROCEDURE set_context(p_user_gender VARCHAR2);
END xxhx_vpd_pkg;
e. 注册为对象注册策略
BEGIN

DBMS_Rls.Add_Policy( object_schema
=>'APPS',

object_name
=>'HX_VPD_TEST',

policy_name
=>'HX_VPD_GENDER',

function_schema => 'APPS',

policy_function =>'XXHX_VPD_PKG.GENDER_VALID',


policy_type => DBMS_RLS.SHARED_CONTEXT_SENSITIVE);


END;
查看结果:

[img=300,252]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
f. 查看策略函数返回的条件

[img=300,105]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
g. 查看使用策略后查看F的结果

[img=300,150]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
h. 查看使用策略后,性别为 M
结果

[img=300,157]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
i.但当我们开一个新窗口,再查询的时候就没有结果,(和PO_headers没有数据有点似曾相识了)
[img=300,123]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]

到这里我们学会了2.4.1中DBA的招数,但MOAC是怎样使用VPD的呢?其实就是和我们的例子一样,也许到这个地方你心里应该会对1.1.3中的小悬念有点底了,或许已经知道怎么去解决这个问题了?如果没有明白,那只能怪我的笔拙,不过没关系,继续讨论MOAC中是怎样使用VPD来实现多OU的安全性控制了。
2.4.3.
MOAC中VPD的使用
在这一节中,我们按照2.4.2的实例来整理MOAC中的VPD的实现步骤,从而解决PO_HEADERS无数据之谜。我们现在知道我们使用的对象名为PO_HEADERS,我的步骤如下:
a. 查看策略函数
SELECT *

FROM dba_policies DBA


WHERE dba.object_name = 'PO_HEADERS';

结果

[img=300,240]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
结果分析:
从该结果中可以得到策略函数是MO_GLOBAL.ORG_SECURITY;
b. 查看可能涉及的Application Context:

SELECT *

FROM dba_context dc


WHERE package = 'MO_GLOBAL'

结果:


结果分析:
从该结果中可以得到在MO_GLOBAL.中使用了两个Application Context,但我们不能肯定都是我们需要的,需要进入MO_GLOBAL.ORG_SECURITY函数中检查;
c. MO_GLOBAL.ORG_SECURITY分析


FUNCTION org_security(obj_schema VARCHAR2,


obj_name
VARCHAR2) RETURN VARCHAR2 IS


l_ci_debug fnd_profile_option_values.profile_option_value%TYPE := NULL;


BEGIN


--


--
Returns different predicates based on the access_mode


--
The codes for access_mode are


--
M - Multiple OU Access


--
A - All OU Access


--
S - Single OU Access


--
Null - Backward Compatibility - CLIENT_INFO case
--


--
The Predicates will be appended to Multi-Org synonyms


IF obj_name = 'AR_PAYMENT_SCHEDULES' AND g_access_mode = 'S' THEN

RETURN 'org_id = sys_context(''multi_org2'',''current_org_id'') OR (org_id = -3116)';


ELSIF g_access_mode IS NOT NULL THEN


IF g_access_mode = 'M' THEN


RETURN 'EXISTS (SELECT 1

FROM mo_glob_org_access_tmp oa

WHERE oa.organization_id = org_id)';

ELSIF g_access_mode IN ('A', 'B') THEN


RETURN 'org_id <> -3113'; -- Bug5109430 filter seed data from policy predicate


ELSIF g_access_mode = 'S' THEN


RETURN 'org_id = sys_context(''multi_org2'',''current_org_id'')';


ELSIF g_access_mode = 'X' THEN


RETURN '1 = 2';


END IF;


ELSE


-- This section is used reserved for debugging using CLIENT_INFO


-- Interim solution for MFG teams


fnd_profile.get('FND_MO_INIT_CI_DEBUG',


l_ci_debug);


IF l_ci_debug = 'Y' THEN


RETURN 'org_id = substrb(userenv(''CLIENT_INFO''),1,10)';


ELSE


RETURN '1=2';


END IF;


END IF;

END org_security;


分析:
第一个条件

IF obj_name = 'AR_PAYMENT_SCHEDULES' AND g_access_mode = 'S' THEN
RETURN 'org_id = sys_context(''multi_org2'',''current_org_id'') OR (org_id = -3116)';
关于对象AR_PAYMENT_SCHEDULES,在dba_policies表中查看策略函数是GLOBAL. ORG_SECURITY_GLOBAL,对于该方法有段注释This is a restricted policy function to support global data -3116.所以这个条件可以忽略。
第二个条件
IF g_access_mode = 'M' THEN


RETURN 'EXISTS (SELECT 1

FROM mo_glob_org_access_tmp oa

WHERE oa.organization_id = org_id)';


这个条件就是实现多ou的判断条件,如果当前的访问模式是’M’,并且数据的org_id也在session表mo_glob_org_access_tmp中,那么这条数据是安全的。
第三个条件

ELSIF g_access_mode IN ('A', 'B') THEN

RETURN 'org_id <> -3113'; -- Bug5109430 filter seed data from policy predicate

“该 Bug 不是公众可访问的 Bug (未公开)”这是我在metalink上查找Bug5109430的信息,不过有注释表明access _Mode=A是预留到将来使用,我估计access _Mode=B也是为了将来使用。
第四个条件
ELSIF g_access_mode = 'S' THEN

RETURN 'org_id = sys_context(''multi_org2'',''current_org_id'')';

该条件的却很简单,单OU模式下返回和Org_id=上下文值
的记录

第五个条件
ELSIF g_access_mode = 'X' THEN

RETURN '1 = 2';

返回nothing 不知道有什么用。
接下来使用了一个预制文件'FND_MO_INIT_CI_DEBUG',我们可以查到他的用处:“MO:设置 Client_Info 以进行调试它的说明是“此配置文件仅限 Oracle 用于调试用途。”
在上面的分析中,我们得出该系统使用了临时表mo_glob_org_access_tmp和上下文sys_context(''multi_org2'',''current_org_id'')的值,可见和我们前面2.3,2.3的分析联系了起来了。也明白了PO_HEADRES查询不到数据的原因,可能是mo_glob_org_access_tmp和上下文sys_context(''multi_org2'',''current_org_id'')的值为空。
d. 初始化环境:
在2.3.3的分析过程中,我们知道mo_global.set_policy_context可以设置环境的初始化,如果能将这章理解,我觉得完全能够解决PO_HEADERS没有数据的问题,以及类似的问题。


2.4.4.
总结
在这一节中,我们将前面分析的结果和前面值的生成分析很好的结合起来,但是使用mo_global.set_policy_context对单OU模式和多OU模式的初始化,是否都能达到我们的要求呢?除开这个方法还会有其它的方法吗?建议有兴趣的先试试,接下来想就开发过程中需要注意地方和方法进行一些介绍。



3.
技术实施要点


3.1.
环境初始化3.1.1.
环境初始化
a.进入一个新窗口执行发票查询(类似于POAP 模块也是多OU)

[img=300,75]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
b.查看我们的首选项表:

[img=300,200]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
c. 查看我们在多OU成功时能访问的表

[img=300,137]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
d. OU模式下的Org_id
BEGIN

fnd_global.apps_initialize(user_id
=> 1230,


resp_id
=> 50541,


resp_appl_id => 200);



mo_global.set_policy_context('S',


'81');

END;

[url=mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht!][img=281,146]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img][/url]
这里插一点,fnd_global.apps_initialize的作用是环境初始化,初始化该环境后,我们可以使用fnd_global.user_id这类的变量,但多OU的初始化仅这样是明显不够的。
e. OU模式下使用mo_global.set_policy_context('M', ')方法进行访问,但结果却是失败的(在新的session下测试)
BEGIN

fnd_global.apps_initialize(user_id
=> 1230,


resp_id
=> 50541,


resp_appl_id => 200);


mo_global.set_policy_context('M',


'');

END;

[img=300,162]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
f. 根据前面的分析,是因为我们没有向po_glob_org_access_tmp表中插值,使用mo_global.init('SQLAP'),一切OK!!
BEGIN

fnd_global.apps_initialize(user_id
=> 1230,


resp_id
=> 50541,


resp_appl_id => 200);


mo_global.init('SQLAP');

END;
/

[img=300,162]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]










3.2.
并发请求3.2.1.
并发请求
在R12中提交请求需要设置并发程序的OU模式,


路径:系统管理->并发->程序选出自己的程序,更新,选出自己的程序,更新,在请求页面选择业务实体模式,设置好该处后如果没有设置预制文件“MO:默认业务实体”在请求提交的过程中会弹出下拉列表让用户选择相应的业务实体。
[img=300,149]mhtml:file://D:\My Documents\Oracle EBS R12\报告提交平台 ? 王浩鑫 EBS R12 MOAC原理探索(添加附件下载).mht![/img]
原理如下
New column MULTI_ORG_CATEGORY in FND_CONCURRENT_PROGRAMS
• Values
– ‘S’ = Single Org
– ‘M’ = Multi Org
• In upgrade, for programs where definition has been customized, value is null and concurrent program will NOT run.
• Script. to set value
UPDATE fnd_concurrent_programs



SET multi_org_category = { 'S‘ or ‘M’}

WHERE CONCURRENT_PROGRAM_NAME = '{Program Name}'


3.3.
Form开发3.3.1.
Form开发
现在还没有涉及到form开发,如果有机会再补上,提供一个讲解的文档,
metlink no: 420787.1
White Paper
Oracle Applications Multiple Organizations Access Control for Custom Code


4.
附录


4.1.
VPD实例源码4.1.1.sql
--建立测试表
CREATE TABLE hss.vpd_test(

ID NUMBER,


NAME VARCHAR2(100),


gender CHAR(1)

);


--插入测试值
INSERT INTO hss.vpd_test VALUES(1,'hansen','M');
INSERT INTO hss.vpd_test VALUES(2,'tea','M');
INSERT INTO hss.vpd_test VALUES(3,'tiger','F');
INSERT INTO hss.vpd_test VALUES(4,'coffee','F');
COMMIT;


SELECT * FROM hss.vpd_test ;


--建立同义词
CREATE SYNONYM HX_VPD_TEST For hss.vpd_test;
SELECT * FROM hx_vpd_test;


--建立应用上下文
CREATE CONTEXT HX_VPD USING apps.XXHX_VPD_PKG;


SELECT *

FROM dba_context


WHERE PACKAGE = 'XXHX_VPD_PKG';



--注册策略
BEGIN

DBMS_Rls.Add_Policy( object_schema
=>'APPS',


object_name
=>'HX_VPD_TEST',


policy_name
=>'HX_VPD_GENDER',


function_schema => 'APPS',


policy_function =>'XXHX_VPD_PKG.GENDER_VALID',


policy_type => DBMS_RLS.SHARED_CONTEXT_SENSITIVE);



END;
/


--查看返回结果
SELECT xxhx_vpd_pkg.gender_valid('APPS',

'HX_VPD_TEST')


FROM dual;



--设置应用初始值
BEGIN

xxhx_vpd_pkg.set_context('');


dbms_output.put_line(sys_context('HX_VPD','GENDER'));

END;
/


SELECT * FROM HX_VPD_TEST;


--查看设置文件信息
SELECT *

FROM dba_policies dba


WHERE dba.object_name = 'HX_VPD_TEST';



4.1.2.
pkg
CREATE OR REPLACE PACKAGE XXHX_VPD_PKG IS

/*==================================================

author:


Hansen.wang


Program Name:


XXHX_VPD_PKG


Description:


pakcage的功能是建立策略函数gender_valid

设置应用程序上下文值



History:


1.00
2008-11-28
hansen
Creation


==================================================*/




/*==================================================

Function Name :


gender_valid


Description:


安全策略函数必须带2个参数:第1个参数是方案名

(或用户名)、第2个参数是方案对象名(或表名、

视图名)。该函数返回附加到SQL语句的where子句

后面的字符串.即使在安全策略函数中不使用也要带

上所述2个参数,否则在执行时会出现“ORA-28112:

无法执行策略函数的错误提示。

Argument:


obj_schame
方案名

obj_name
方案对象名

Return



安全策略字符串

History:


1.00
2008-11-28
hansen
Creation


==================================================*/



FUNCTION gender_valid(obj_schame VARCHAR2,

obj_name
VARCHAR2) RETURN VARCHAR2;



/*==================================================

Function Name :


set_context


Description:


该方法用于设置应用程序上下文的值

Argument:


p_user_gender
性别


History:


1.00
2008-11-28
hansen
Creation


==================================================*/




PROCEDURE set_context(p_user_gender VARCHAR2);
END xxhx_vpd_pkg;


CREATE OR REPLACE PACKAGE BODY xxhx_vpd_pkg IS



/*==================================================

Function Name :


gender_valid


Description:


安全策略函数必须带2个参数:第1个参数是方案名

(或用户名)、第2个参数是方案对象名(或表名、

视图名)。该函数返回附加到SQL语句的where子句

后面的字符串.即使在安全策略函数中不使用也要带

上所述2个参数,否则在执行时会出现“ORA-28112:

无法执行策略函数的错误提示。

Argument:


obj_schame
方案名

obj_name
方案对象名

Return


安全策略字符串

History:


1.00
2008-11-28
hansen
Creation


==================================================*/



FUNCTION gender_valid(obj_schame VARCHAR2,

obj_name
VARCHAR2) RETURN VARCHAR2 AS

predicate VARCHAR2(2000);

BEGIN

predicate := ' gender = sys_context(''HX_VPD'', ''Gender'')';

RETURN predicate;

END;



/*==================================================

Function Name :


set_context


Description:


该方法用于设置应用程序上下文的值

Argument:


p_user_gender
性别


History:


1.00
2008-11-28
hansen
Creation


==================================================*/



PROCEDURE set_context(p_user_gender VARCHAR2) IS

BEGIN

dbms_session.set_context('HX_VPD',

'GENDER',


p_user_gender);

EXCEPTION

WHEN OTHERS THEN

NULL;

END set_context;
END xxhx_vpd_pkg;




4.2.
参考文档4.2.1.
参考文档
a. Meta. link NO. 462383.1—— SQL Queries and Multi-Org Architecture in Release 12
b. Meta. link NO.
732826.1
——Discoverer 10g (10.1.2) Querying Against An E-Business Suite R 12 Multi-Org VPD Protectected View With ORG_ID
c. Meta. link NO.
415860.1 ——How to view org-specific data in a MOAC environment
d. Meta. link NO.
420787.1
——Oracle Applications Multiple Organizations Access Control for Custom Code
e. Meta. link NO.
414003.1
——MOAC Feature And MOAC Uptake in Oracle Projects
f. Meta. link NO.
174368.1
——Policies on Synonyms
g. http://www.oracleappshub.com/release12/moac-from-multi-orgto-multi-access/

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26101098/viewspace-703361/,如需转载,请注明出处,否则将追究法律责任。

下一篇: 会计期间状态
请登录后发表评论 登录
全部评论

注册时间:2011-07-27

  • 博文量
    43
  • 访问量
    81354