AUTHORITY-CHECK 与 SQL 动态 WHERE 语句

举报
雨绸缪 发表于 2023/05/26 18:02:24 2023/05/26
【摘要】 ABAP 功能模块检查 SAP 用户的授权对象。 ABAP 程序员可以使用功能模块 AUTHORITY_CHECK 来验证 SAP 用户是否具有所需的权限对象权限。语法:AUTHORITY-CHECK OBJECT auth_obj [FOR USER user] ID id1 { FIELD val1 } | DUMMY [ID id2 { FIELD val2 } | ...

image.png

ABAP 功能模块检查 SAP 用户的授权对象。 ABAP 程序员可以使用功能模块 AUTHORITY_CHECK 来验证 SAP 用户是否具有所需的权限对象权限。

语法:

AUTHORITY-CHECK OBJECT auth_obj [FOR USER user]
    ID id1  { FIELD val1 } | DUMMY  
    [ID id2 { FIELD val2 } | DUMMY ]
    ...  
    [ID id10 { FIELD val10 } | DUMMY ].

此语句检查是否在当前用户的用户主记录中输入授权或在 user 中指定的用户为字段 auth_obj 中输入的授权对象输入授权,以及此授权是否足以满足语句中指定的请求。 auth_obj 需要一个类似字符的平面字段,其中包含授权对象的名称。如果不指定添加FOR USER,则检查当前用户的权限。

如果指定了 id1 ... id10,则必须为相关授权对象指定至少一个且最多 10 个不同的授权字段。 id1 ... id10期望包含大写授权字段名称的类似字符的平面字段。如果指定的授权字段未出现在授权对象中,则无法进行检查,并且 sy-subrc 设置为 4。

只能对 CHAR 字段执行检查。所有其他字段类型都会导致“未授权”。

例如,我想检查 SAP 用户是否对 SAP Screen Personas 3.0 管理事务 /PERSONAS/ADMIN 中的所有功能具有完全管理访问权限, ABAP 程序员可以在他们的 SAP 报表中使用 AUTHORITY_CHECK 功能模块来测试用户是否具有具有 01 管理活动权限的授权对象 P_ADMIN。

如果启动 SAP tcode SU21,维护 PERS 类 P_ADMIN 授权对象下的授权对象事务用于“角色管理员授权对象”。

CALL FUNCTION 'AUTHORITY_CHECK'
   EXPORTING
      user = sy-uname
      object = 'P_ADMIN'
      field1 = 'P_ACTVT_AD'
      value1 = '01'
   EXCEPTIONS
      user_dont_exist = 1
      user_is_authorized = 2
      user_not_authorized = 3
      user_is_locked = 4
    OTHERS = 5.
IF sy-subrc <> 0.
* Implement suitable error handling here
ELSE.
* User is authorized
ENDIF.

以上示例 ABAP 代码块和简短的 SU21 指南将帮助程序员在 ABAP 代码中动态检查用户是否具有授权对象权限。

根据用户授权生成动态 WHERE 条件

检查单个值的授权很容易。例如,如果我们只需要检查用户是否获得某个销售组织的授权,我们可以通过对象 V_VBAK_VKO 进行授权检查:

AUTHORITY-CHECK OBJECT 'V_VBAK_VKO'
         ID 'VKORG' FIELD 'A001'
         ID 'VTWEG' DUMMY
         ID 'SPART' DUMMY
         ID 'ACTVT' FIELD '03'.

如果要检查多个销售组织,通常有两种选择:

  1. 选择 SAP 系统中所有可用的销售组织。然后 LOOP 对结果集进行授权检查并构建一个范围表,其中包含所有允许的销售组织。该范围随后将添加到 SQL 语句的 WHERE 条件中。
  2. 先选择数据。然后 LOOP 对数据库结果进行必要的权限检查,将用户没有权限的数据从结果集中移除。

第二种选择有一个明显的缺点,即最终从数据库中选择的数据多于所需的数据。即使像 SAP HANA 这样的内存数据库系统速度很快,也应该避免这种情况。

CL_AUTH_OBJECTS_TO_SQL 类提供了一些方便的方法,可以用更少的代码实现第一个选项。

生成 WHERE 条件

首先,我们需要调用方法 CREATE_FOR_OPEN_SQL 来获取 CL_AUTH_OBJECTS_TO_SQL 的新实例。然后,通过方法 ADD_AUTHORIZATION_OBJECT 添加要检查的授权对象,如下面的代码示例所示。

DATA(authsql) = cl_auth_objects_to_sql=>create_for_open_sql( ).

authsql->add_authorization_object(
  EXPORTING
    iv_authorization_object = 'V_VBAK_VKO'
    it_activities = VALUE #( ( auth_field = 'ACTVT' value = '03' ) )
    it_field_mapping = VALUE #(
      ( auth_field = 'VKORG'
        view_field = VALUE #( table_ddic_name = 'VBAK' field_name = 'VKORG' ) ) ) )
    it_filter = VALUE #( FOR selopt IN s_vkorg[]
      ( auth_field = 'VKORG' low = selopt-low high = selopt-high ) ) 
).   

TRY .
    DATA(where) = authsql->get_sql_condition( ).
  CATCH cx_auth_not_authorized.
    " Not authorized at all
ENDTRY.

这些方法需要按如下方式调用:

  • IV_AUTHORIZATION_OBJECT 要检查的授权对象的名称
  • IT_ACTIVITIES 需要检查的授权字段和活动
  • IT_FIELD_MAPPING 字段映射到 DDIC 字段
  • IT_FILTER (可选)过滤器以限制要检查的值。例如,这可能基于选择屏幕中的选择选项,以仅检查用户想要从中选择数据的销售组织。

如果当前用户没有指定对象的授权,则抛出异常 CX_AUTH_NOT_AUTHORIZED 。如果没有限制,方法调用的结果为空。

假设当前用户有权查看销售组织 S000 和 S001 。在这种情况下,变量 where 将如下所示:

( VKORG = 'S000' OR VKORG = 'S001' )

SQL语句中的动态 WHERE

SELECT 语句也可以动态使用。字段列表、实际的 WHERE 子句和表名都可以在运行时定义。这不是很常见,甚至可能难以阅读(对于您的开发人员),可以了解一下。

常规 WHRER 写法:

SELECT ... FROM vbak INTO TABLE @DATA(vbak) WHERE (where).

以下示例显示了一个简单的设置,其中字段列表、where 子句和表名都设置为参数值 - 在调用 SELECT 语句之前:

DATA: lv_fields    TYPE string,  
      lv_clause    TYPE string,  
      lv_tablename TYPE string,  
      lt_results   TYPE TABLE OF matnr.  
  
lv_tablename = 'MARA'.  
lv_fields = 'MATNR'.  
lv_clause = 'MTART = ''Z011'' AND SPART = ''00'''.  
  
SELECT (lv_fields) FROM (lv_tablename)  
  INTO TABLE lt_results  
  UP TO 20 ROWS  
WHERE (lv_clause).  
  
cl_demo_output=>display_data( lt_results ).

输入结果:

image.png

只有当实际结果表也很灵活时,整个设置才有意义。 SAP 在他们的帮助系统中有一个很好的例子,它展示了如何将这样的表定义和准备为 FIELD-SYMBOLS 变量。另外:该示例显示了字段列表和 where 子句的字符串字段。这些也可以是内部表,这可以使编写 where 子句更容易一些。编码示例:

data: lv_snnn_table(4) type c, 
      lv_select_clause type string. 
field-symbols: <fs_table_snnn> type standard table.

* Prepare the logic according to the selection you need
case what_i_need. 
  when 'ZORBA'
    lv_snnn_table = 'S920'. 
    lv_select_clause = 'VRSIO = ''000'' ' &&
      'MATNR IN GR_MATNR'.
  when 'ZEBRO'.
    lv_snnn_table = 'S920'. 
*... more variations
endcase. 
  
select * into corresponding 
  fields of table  <fs_table_snnn>
  from (lv_snnn_table)
  where (lv_select_clause).

当访问这里选择的信息时,你应该考虑到字段是事先不知道的,所以像 <fs_table_snnn>-VRSIO 这样的字段将不会编译。看看下一段代码:

field-symbols: <fs_wa_snnn> type any, 
                <VERSION> type any, 
                <MATERIAL> type matnr. 

* Compose a select clause - for the LOOP
lv_select_clause = 
  'MATNR = '' && lv_my_material &&
  '' and PROCESSED = abap_false'. 
LOOP AT <fs_table_snnn> ASSIGNING <fs_wa_snnn>
  WHERE (lv_select_clause).

  ASSIGN COMPONENT 'VRSIO' 
    OF STRUCTURE <fs_wa_snnn> TO <VERSION>.
  ASSIGN COMPONENT 'MATNR' 
    OF STRUCTURE <fs_wa_snnn> TO <MATERIAL>.

  IF <MATERIAL> IS ASSIGNED.
* Do your thing here
  ENDIF. 
ENDLOOP. 

这里显示了一些字段符号访问方法。循环分配和分配组件是访问数据的关键。也可以使用 RH_DYNAMIC_WHERE_BUILD 在 ABAP SELECT 查询中编写动态 where 子句。

data : begin of itab occurs 0,
         matnr like mara-matnr,
end of itab.

ypes: begin of ty_s_clause.
types:   line(72)  type c.
types: end of ty_s_clause.

data : begin of gt_condtab occurs 0.
        include structure hrcond.
data : end   of gt_condtab.

FIELD-SYMBOLS <fs_wherecond> TYPE ty_s_clause.
data:
  gt_where_clauses  type standard table of ty_s_clause
                    with default key.


gt_condtab-field = 'MATNR'.
gt_condtab-opera = 'EQ'.
gt_condtab-low = '000000000000000111'.
append  gt_condtab.
clear  gt_condtab.

call function 'RH_DYNAMIC_WHERE_BUILD'
  exporting
    dbtable         = space " can be empty
  tables
    condtab         = gt_condtab
    where_clause    = gt_where_clauses
  exceptions
    empty_condtab   = 01
    no_db_field     = 02
    unknown_db      = 03
    wrong_condition = 04.
            .
 
select matnr from mara into table itab where (gt_where_clauses).

这个本质也是封装成字符串,但实际开发中这个 FUNCTIOM MODULE 不太建议直接使用。

参考链接:

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。