SAP HCM权限控制浅析

前言


由于太了解自己的重度拖延症,那是不火烧眉毛(主要是担心毁容)就置之脑后了,所以我先对好友把牛吹下了,说我必将花费两周心血研究的HCM权限控制成果写成博客,所以立字为据,如我这般玉树临风、风流倜傥、才高八斗、信守诺言之人,那必定得言出必行。

导言


HCM权限控制有三部分配置,一个是角色配置,另一个是结构化授权配置,另外还有个授权主开关配置。

结构化授权配置是HCM的特殊产物,因为HCM有组织层级,即评估路径O-S-P,组织下有岗位,岗位下有人员,夫妻肺片里没有夫妻,蚂蚁上树里没有蚂蚁,日料店里没有日料。

正文


一、配置点

1、 角色配置

       角色配置使用Tcode PFCG,常用权限对象如下:

权限对象作用示例
PLOG校验人员计划的权限PLVAR:        *
OTYPE:       C,O,P,S,T,US
INFOTYP:   1000,1001
SUBTYP:    *
ISTAT:         *
PPFCODE: DISP,LISD
P_ABAP简化指定程序的权限检查

REPID:  HCNCALC0
COARS:全部值

P_ORGIN校验人员信息类型的权限

INFTY:  0000-9051

SUBTY :*

AUTHC: M,R

PERSA: 9005

PERSG: *

PERSK: *

VDSK1: *

P_PCLX校验PCLx( x =1、 2、 3、4 ) 簇的权限

RELID:  *

AUTHC:*

P_PCR校验工资核算范围的权限ABRKS:MS
ACTVT:*
P_PERNR校验人员编号权限AUTHC:*
PSIGN: *
INFTY:  *
SUBTY:*
2、 结构化授权配置

① 创建权限参数文件,使用Tcode OOSP,示例如下:

       其中期间的选项释义如下:

选项描述期间
 (空)全部19000101—99991231
D关键日期系统当前日期
M当前月系统当前日期所在月初—系统当前日期所在月末
Y当前年系统当前日期所在年初—系统当前日期所在年末
P过期19000101—系统当前日期
F未来系统当前日期—99991231

② 创建权限参数文件,使用Tcode OOSB,示例如下:

3、 授权主开关配置

       授权主开关配置使用Tcode OOAC,示例如下:

       其中常用配置释义如下:

语义缩写描述作用
ADAYSHR:权限检查的时间容差设置一个天数,默认是15,权限调整后这个天数内依然保留权限
ORGINHR: 主数据是否检查权限对象P_ORGIN
ORGPDHR:结构权限检查是否启用结构化授权检查
ORGXXHR:主数据 - 扩展的检查是否检查权限对象P_ORGXX
PERNRHR:主数据 - 个人号检查是否检查权限对象P_PERNR

二、问题点

1、结构化授权无法校验权限有效期间。

此项目有许多人事报表需求,选择屏幕输入期间和组织,即可查询该期间内的组织下所有人员。选择屏幕组织搜索帮助调用函数 HR_COMBINED_SELECTION 或 RH_TYPE_STRUC_HELP,查询调用函数 RH_STRUC_GET,评估路径使用 O-S-P,测试过程中遇到问题点列举如下:

① 问题描述:

 直接下级组织调动,该组织还有下级组织,组织 50021443是根组织 10005200的直接下级组织,2021/04/01调入其他组织,其还有下级组织 50021444,但仅直接下级组织在权限视图里的有效期间更新了,再下级组织的有效期间未更新,如下图所示。

此时报表输入期间2021/04/01及之后的日期,组织搜索帮助由于下下级组织 50021444在选择屏幕期间内无法找到直接上级组织,所以认为该组织也是根组织,这样就会出现多个根组织并列的情况,如下图所示。

解决方法:

在函数 RH_TYPE_STRUC_INDEX 结束处增加隐式增强,判断根节点的上级组织权限是否被截止。

ENHANCEMENT 1  YENH_RH_TYPE_STRUC_INDEX.    "active version
* 由于组织调整,结构化授权视图里只有调整组织有截止日期,下级组织截止日期依然是99991231,
* 这样导致下级组织会显示为单独一个根节点,所以增加一层权限校验,判断上级组织是否权限被截止
  DATA: lt_view  TYPE STANDARD TABLE OF hrview,
        lv_tabix TYPE sy-tabix,
        lv_auth  TYPE char1.

  IF sy-tcode = 'YXHR064' OR SY-CPROG = 'YXHRR064'.
    IF root_object_index[] IS NOT INITIAL.
      SELECT objid, sclas, sobid
        FROM hrp1001
        INTO TABLE @data(lt_uporg)
         FOR ALL ENTRIES IN @root_object_index
       WHERE plvar = @root_object_index-plvar
         AND otype = @root_object_index-otype
         AND objid = @root_object_index-objid
         AND rsign = 'A'
         AND relat = '002'
         AND istat = '1'
         AND begda LE @act_endda
         AND endda GE @act_begda.
    ENDIF.

    PERFORM fill_view(saplrhac) USING act_plvar sy-uname.
    IMPORT view = lt_view FROM MEMORY ID '$PD__VIEW__IN__MEM$'.
    SORT lt_view BY plvar otype objid begda.

    LOOP AT root_object_index.
      CLEAR lv_auth.

      LOOP AT lt_uporg INTO DATA(ls_uporg) WHERE objid = root_object_index-objid.
        READ TABLE lt_view TRANSPORTING NO FIELDS
              WITH KEY plvar = act_plvar
                       otype = ls_uporg-sclas
                       objid = '00000000' BINARY SEARCH.
        IF sy-subrc = 0.
          lv_auth = 'X'.
          EXIT.
        ELSE.
          READ TABLE lt_view TRANSPORTING NO FIELDS
                WITH KEY plvar = act_plvar
                         otype = ls_uporg-sclas
                         objid = ls_uporg-sobid BINARY SEARCH.
          IF sy-subrc <> 0.
            lv_auth = 'X'.
            EXIT.
          ELSE.
            lv_tabix = sy-tabix.
            LOOP AT lt_view INTO DATA(ls_view) FROM lv_tabix.
              IF  ls_view-plvar <> act_plvar
               OR ls_view-otype <> ls_uporg-sclas
               OR ls_view-objid <> ls_uporg-sobid.
                EXIT.
              ENDIF.

              IF ls_view-begda <= act_endda AND ls_view-endda >= act_begda.
                lv_auth = 'X'.
                EXIT.
              ENDIF.
            ENDLOOP.
          ENDIF.
        ENDIF.
      ENDLOOP.
      IF sy-subrc = 0 AND lv_auth IS INITIAL.
        DELETE TABLE root_object_index.
      ENDIF.
    ENDLOOP.
  ENDIF.
ENDENHANCEMENT.

② 问题描述:

直接下级组织调动,组织 10005201是根组织 10005200的直接下级组织,2023/05/11调入其他组织,权限有效期间已更新,如下图所示。

但SAP标准校验结构化授权对象使用函数RH_STRU_AUTHORITY_CHECK,此函数仅检查权限视图是否包含检查对象,但并不校验期间。

 所以当报表输入查询期间2023/05/11及之后的日期,组织输入10005201,依然有权限查看数据。

解决方法:

在函数 RH_STRUC_GET 的结束处增加隐式增强,增加一重校验,检查查询组织的权限期间。

ENHANCEMENT 1  YENH_RH_STRUC_GET.    "active version
* 1. 标准组织权限检查不包含期间,即之前有权限的组织则一直有权限,
*    所以组织调动后还能查询该组织信息,因此校验结构化授权再加一重期间校验
* 2. 由于组织调整,结构化授权视图里只有调整组织有截止日期,下级组织截止日期依然是99991231,
*    这样导致下级组织依然有权限,所以增加一层权限校验,判断上级组织是否权限被截止
* 3. 由于根组织与上级组织上下级关系发生变化,互为上下级组织,上级组织截止日期不再是99991231,
*    此处查询会导致无数据,所以如果查询组织是根组织则不用校验

  DATA: lt_view  TYPE STANDARD TABLE OF hrview,
        lt_struc TYPE STANDARD TABLE OF struc,
        lv_objid TYPE t77pr-objid,
        lv_tabix TYPE sy-tabix,
        lv_auth  TYPE char1.

  IF authority_check = 'X' AND 'O-S-P' CS act_otype.
*   由于根组织与上级组织上下级关系发生变化,互为上下级组织,
*   此处查询会导致无数据,所以如果查询组织是根组织则不用校验
    SELECT SINGLE t77pr~objid
      INTO @lv_objid
      FROM t77ua
     INNER JOIN t77pr
        ON t77ua~profl = t77pr~profl
     WHERE t77ua~uname = @sy-uname
       AND t77pr~plvar = @act_plvar
       AND t77pr~otype = @act_otype
       AND t77pr~objid = @act_objid.
    IF sy-subrc <> 0.
      PERFORM fill_view(saplrhac) USING act_plvar sy-uname.
      IMPORT view = lt_view FROM MEMORY ID '$PD__VIEW__IN__MEM$'.
      SORT lt_view BY plvar otype objid begda.

      READ TABLE lt_view TRANSPORTING NO FIELDS
            WITH KEY plvar = act_plvar
                     otype = act_otype
                     objid = '00000000' BINARY SEARCH.
      IF sy-subrc <> 0.
*       检查查询组织是否权限被截止
        READ TABLE lt_view TRANSPORTING NO FIELDS
              WITH KEY plvar = act_plvar
                       otype = act_otype
                       objid = act_objid BINARY SEARCH.
        IF sy-subrc = 0.
          lv_tabix = sy-tabix.
          LOOP AT lt_view INTO DATA(ls_view) FROM lv_tabix.
            IF  ls_view-plvar <> act_plvar
             OR ls_view-otype <> act_otype
             OR ls_view-objid <> act_objid.
              EXIT.
            ENDIF.

            IF ls_view-begda <= act_endda AND ls_view-endda >= act_begda.
              lv_auth = 'X'.
              EXIT.
            ENDIF.
          ENDLOOP.
        ENDIF.
        IF lv_auth IS INITIAL.
          REFRESH: result_tab, result_objec, result_struc.
          MESSAGE e170(5w) WITH act_plvar act_otype
                                act_objid act_wegid
                                RAISING no_entry_found.
        ENDIF.

*       检查上级组织是否权限被截止
        IF act_wegid CS 'O-S-P' AND act_otype = 'O'.
          CALL FUNCTION 'RH_STRUC_GET'
            EXPORTING
              act_otype              = act_otype
              act_objid              = act_objid
              act_wegid              = 'O-O'
              act_plvar              = act_plvar
              act_begda              = act_begda
              act_endda              = act_endda
              authority_check        = ''
           TABLES
             result_struc           = lt_struc
           EXCEPTIONS
             no_plvar_found         = 1
             no_entry_found         = 2
             OTHERS                 = 3.
          IF sy-subrc = 0.
            LOOP AT lt_struc INTO DATA(ls_struc) FROM 2.
*             检查是否有权限被截止的上级组织
              READ TABLE lt_view INTO ls_view
                    WITH KEY plvar = act_plvar
                             otype = ls_struc-otype
                             objid = ls_struc-objid BINARY SEARCH.
              IF sy-subrc = 0.
                IF ls_view-begda > act_endda OR ls_view-endda < act_begda.
                  CLEAR lv_auth.

*                 检查同级别期间是否有有权限的组织
                  LOOP AT lt_struc INTO DATA(ls_struc_level) WHERE level = ls_struc-level.
                    READ TABLE lt_view TRANSPORTING NO FIELDS
                          WITH KEY plvar = act_plvar
                                   otype = ls_struc_level-otype
                                   objid = ls_struc_level-objid BINARY SEARCH.
                    IF sy-subrc = 0.
                      lv_tabix = sy-tabix.
                      LOOP AT lt_view INTO ls_view FROM lv_tabix.
                        IF  ls_view-plvar <> act_plvar
                         OR ls_view-otype <> ls_struc_level-otype
                         OR ls_view-objid <> ls_struc_level-objid.
                          EXIT.
                        ENDIF.

                        IF ls_view-begda <= act_endda AND ls_view-endda >= act_begda.
                          lv_auth = 'X'.
                          EXIT.
                        ENDIF.
                      ENDLOOP.
                    ENDIF.
                    IF lv_auth = 'X'.
                      EXIT.
                    ENDIF.
                  ENDLOOP.

                  IF lv_auth IS INITIAL.
                    REFRESH: result_tab, result_objec, result_struc.
                    MESSAGE e170(5w) WITH act_plvar act_otype
                                          act_objid act_wegid
                                          RAISING no_entry_found.
                  ENDIF.
                ENDIF.
              ENDIF.
            ENDLOOP.
          ENDIF.
        ENDIF.
      ENDIF.
    ENDIF.
  ENDIF.

ENDENHANCEMENT.
2、工资核算结果报表无法区分人事专员和薪酬专员权限。

问题描述:

譬如某家公司的人事专员和薪酬专员皆有该公司人事范围的权限,那使用逻辑数据库PNP 选择屏幕900 或者函数 PYXX_READ_PAYROLL_RESULT 读取工资核算结果皆可查看数据。

这是由于SAP标准查看工资核算结果Tcode PC_PAYRESULT校验了人员基本工资0008信息类型的权限,校验期间先用系统当前日期,如若系统当前日期没有权限则再校验工资核算结果最新历经结束日期的权限,如若都无权限则不可查看。而逻辑数据库PNP 和函数 PYXX_READ_PAYROLL_RESULT无该校验。

解决方法:

由于逻辑数据库PNP 查询工资核算结果底层也是调用的函数 PYXX_READ_PAYROLL_RESULT,所以在函数 PYXX_READ_PAYROLL_RESULT 结束处增加隐式增强,增加一重校验,检查人员基本工资0008信息类型的权限。

ENHANCEMENT 1  YENH_PYXX_READ_PAYROLL_RESULT.    "active version
* 参照Tcode PC_PAYRESULT(程序CONSTRUCTOR (CL_HR_LSTCE_EMPLOYEE))增加人员0008信息类型检查
* check read-authority for infotype 0008
  IF check_read_authority = 'X'.
    CALL FUNCTION 'HR_CHECK_AUTHORITY_INFTY'
      EXPORTING
        tclas            = 'A'
        pernr            = employeenumber
        infty            = '0008'
        subty            = ''
        begda            = sy-datum
        endda            = sy-datum
        level            = 'R'
      EXCEPTIONS
        no_authorization = 1.
    IF sy-subrc <> 0.
      ASSIGN COMPONENT 'INTER' OF STRUCTURE payroll_result
                    TO FIELD-SYMBOL(<ls_inter>).
      IF sy-subrc = 0.
        ASSIGN COMPONENT 'VERSC' OF STRUCTURE <ls_inter>
                      TO FIELD-SYMBOL(<lv_versc>).
        IF sy-subrc = 0.
          ASSIGN COMPONENT 'FPEND' OF STRUCTURE <lv_versc>
                        TO FIELD-SYMBOL(<lv_fpend>).
          IF sy-subrc = 0.
            DATA(lv_fpend) = conv datum( <lv_fpend> ).

*           second chance: check with payroll_until
            CALL FUNCTION 'HR_CHECK_AUTHORITY_INFTY'
              EXPORTING
                tclas            = 'A'
                pernr            = employeenumber
                infty            = '0008'
                subty            = ''
                begda            = lv_fpend
                endda            = lv_fpend
                level            = 'R'
              EXCEPTIONS
                no_authorization = 1.
            IF sy-subrc <> 0.
              CLEAR payroll_result.
              MESSAGE i018 WITH clusterid
              RAISING no_read_authority.
            ENDIF.
          ENDIF.
        ENDIF.
      ENDIF.
    ENDIF.
  ENDIF.

ENDENHANCEMENT.

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值