AUTHORITY-CHECK 与 SQL 动态 WHERE 语句
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'.
如果要检查多个销售组织,通常有两种选择:
- 选择 SAP 系统中所有可用的销售组织。然后
LOOP
对结果集进行授权检查并构建一个范围表,其中包含所有允许的销售组织。该范围随后将添加到 SQL 语句的WHERE
条件中。 - 先选择数据。然后 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 ).
输入结果:
只有当实际结果表也很灵活时,整个设置才有意义。 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 不太建议直接使用。
参考链接:
- 点赞
- 收藏
- 关注作者
评论(0)