使用 AUTHORITY-CHECK 语句

学习目标

  • 使用 AUTHORITY-CHECK 语句。

AUTHORITY-CHECK 语句

要显式执行权限检查,请使用 AUTHORITY-CHECK 语句。在其中,指定要检查的权限对象以及所需值。此处的 AUTHORITY-CHECK 针对对象 /DMO/TRVL 执行检查,并要求用户具有包含字段 /DMO/CNTRY 的值 US 以及字段 ACTVT 的值 03 的权限。

如何检查权限检查的结果

与 CDS 访问控制附带的已过滤权限检查不同,AUTHORITY-CHECK 语句不会阻止用户查看他们没有权限的数据。

AUTHORITY-CHECK 在系统字段 sy-subrc 中放置返回代码。通过在权限检查后立即检查 sy-subrc 的值,您可以找出检查是否成功。

如果权限检查成功,sy-subrc 的值为 0。sy-subrc 的其他值表示检查失败:

  • 值 4 表示用户对相应对象具有权限,但不具有正确的值。

  • 值 12 表示用户根本没有相应对象的权限。

如果权限检查失败,则必须确保用户自己无法访问数据。

在此示例中,权限检查要求用户对国家/地区 'US' 具有权限。由于我们的用户不是这种情况,因此 sy-subrc 在权限检查后不等于零。在这种情况下,应用显示文本 无权限

如何使用 AUTHORITY-CHECK 语句

观看此视频,了解如何使用权限检查语句。

视频:本节含 SAP 官方视频(视频 ID 1_5e81bjfl),需在 learning.sap.com 在线观看。

实施权限检查

您意识到您的代码使用户可以访问他们无权查看的数据。要修改此项,首先从定义了 CDS 访问控制的 CDS 视图实体中读取代码。然后实施显式权限检查,以便能够区分用户无权查看的数据和根本不存在的数据。

模板:

  • /LRN/CL_S4D401_ITS_SEC_KEY(全局类)

解决方案:

  • /LRN/CL_S4D401_ACS_AUTH_CHECK(全局类)

任务 1: 复制模板(可选)

复制模板类 /LRN/CL_S4D401_ITS_SEC_KEY。如果已完成上一练习,则可以跳过此任务并继续编辑类 ZCL_##_SOLUTION

步骤

  1. 将类 /LRN/CL_S4D401_ITS_SEC_KEY 复制到您自己的包中的类(建议名称:ZCL_##_SOLUTION,其中 ## 代表组编号)。

  2. 在项目浏览器中,右键单击类 /LRN/CL_S4D401_ITS_SEC_KEY 以打开上下文菜单。

  3. 从上下文菜单中,选择复制....

  4. 在包字段中输入的名称。在名称字段中,输入 ZCL_##_SOLUTION,其中 ## 代表组编号。

  5. 选择下一步

  6. 确认传输请求并选择完成

  7. 激活复制。

  8. Ctrl + F3 激活类。

任务 2: 分析权限

从数据库表 /LRN/CARRIER 开始,找到保护承运商数据免受未授权访问的 CDS 访问控制。分析 CDS 访问控制以找出用户显示承运方数据所需的权限。

步骤

  1. 显示数据库表 /LRN/CARRIER 的定义。

  2. Ctrl + Shift + A 并在搜索字段中输入 /LRN/CARRIER

  3. 选择确定

  4. 分析此数据库表的使用位置清单

  5. 在数据库表 /LRN/CARRIER 的定义中,右键单击 /lrn/carrier 并选择获取调用清单。或者,单击 /lrn/carrier 并按 Ctrl + Shift + G

  6. 在选择对象类型对话框中,确保至少选择对象类型**数据定义**,然后选择完成

  7. 在编辑器下方的搜索视图中,选择漏斗图标以打开过滤器对话框。

  8. 将光标置于对象类型字段中,然后按 **Ctrl + 空格**打开值帮助对话框。

  9. 从建议列表中选择 DDLS/DF(数据定义),然后选择应用

  10. 分析 CDS 视图 **/LRN/I_CARRIER**的使用位置清单

  11. 在搜索视图中,右键单击 /LRN/I_CARRIER(数据定义),然后选择获取使用位置清单。或者,单击 */LRN/I_CARRIER(数据定义)*并按 Ctrl + Shift + G

  12. 在选择对象类型对话框中,确保至少选择对象类型**访问控制**,然后选择完成

  13. 如果编辑器下方的搜索视图显示的搜索结果过多,请选择漏斗图标以打开过滤器对话框。将光标置于对象类型字段中,然后按 **Ctrl + 空格**打开值帮助对话框。从建议清单中选择 DCLS/DL(访问控制),然后选择应用

  14. 打开访问控制 /LRN/I_CARRIER 的定义。

  15. 在搜索视图中,双击 /LRN/I_CARRIER(访问控制)

  16. 权限对象名称是函数 pfcg_auth 的第一个输入参数。

  17. 其他输入参数为权限对象的权限字段提供值。

  18. 打开权限对象 /LRN/CARR 的定义以分析活动值的含义。

  19. 按住 Ctrl 键并单击函数 pfcg_auth 调用中的 /LRN/CARR

  20. 允许的活动下列出可能的活动值。

任务 3: 使用 CDS 访问控制

在本地类 LCL_CARRIER 的**构造函数**方法中,将数据库表 /LRN/CARRIER 替换为 CDS 视图 /LRN/I_CARRIER,该视图受 CDS 访问控制 /LRN/I_CARRIER 保护。使用不同的载体标识作为构造函数输入测试代码。

步骤

  1. 打开局部类 LCL_CARRIER 的**构造函数**方法的实施。

  2. 返回到全局类 ZCL_##_SOLUTION 的代码,其中 ## 是您的组编号。

  3. 大纲 视图中展开 ZCL_##_SOLUTIONLCL_CARRIER ,然后单击 CONSTRUCTOR

  4. 调整 SELECT 语句。在 FROM 子句中,将数据库表 /LRN/CARRIER 替换为上述 CDS 视图。

  5. 如下调整代码:

SELECT SINGLE
*    FROM /lrn/carrier
FROM /LRN/I_Carrier
  1. 修复语法错误。将表字段名称替换为相应的 CDS 视图元素名称。

  2. 如下调整代码:

*  SELECT SINGLE
*    FROM /lrn/carrier
*    FIELDS concat_with_space( carrier_id, name, 1 ), currency_code
*    WHERE carrier_id = @i_carrier_id
*    INTO ( @me->name, @me->currency_code ).
SELECT SINGLE
FROM /LRN/I_Carrier
FIELDS concat_with_space( AirlineID, Name, 1 ), CurrencyCode
WHERE AirlineID = @i_carrier_id
INTO ( @me->name, @me->currency_code ).
  1. 以控制台应用形式激活并测试全局类。

  2. Ctrl + F3

  3. F9

  4. 在全局类中,将本地常量 c_carrier_id 的值更改为 UA

  5. 切换到全局类标签。

  6. 如下调整代码:

*  CONSTANTS c_carrier_id TYPE /dmo/carrier_id VALUE 'LH'.
CONSTANTS c_carrier_id TYPE /dmo/carrier_id VALUE 'UA'.
  1. 以控制台应用形式激活并测试全局类。

  2. Ctrl + F3

  3. F9

任务 4: 实施 AUTHORITY-CHECK 语句

在本地类 LCL_CARRIER 的**构造函数**方法中,如果航班载体存在但用户无权使用此运输公司,则实施 AUTHORITY-CHECK 语句并引发异常 CX_ABAP_AUTH_CHECK_EXCEPTION

步骤

  1. 打开局部类 LCL_CARRIER 的**构造函数**方法的实施。

  2. 确保已在编辑器中打开全局类 ZCL_##_SOLUTION,其中 ## 是您的组编号。

  3. 大纲 视图中展开 ZCL_##_SOLUTIONLCL_CARRIER ,然后单击 CONSTRUCTOR

  4. 调整 SELECT 语句以再次从数据库表 /LRN/CARRIER 中读取。

  5. 如下调整代码:

*  SELECT SINGLE
*    FROM /LRN/I_Carrier
*    FIELDS concat_with_space( AirlineID, Name, 1 ), CurrencyCode
*    WHERE AirlineID = @i_carrier_id
*    INTO ( @me->name, @me->currency_code ).
SELECT SINGLE
FROM /lrn/carrier
FIELDS concat_with_space( carrier_id, name, 1 ), currency_code
WHERE carrier_id = @i_carrier_id
INTO ( @me->name, @me->currency_code ).
  1. 实施在读取访问成功时执行的 AUTHORITY-CHECK 语句,即未引发异常 CX_ABAP_INVALID_VALUE。使用上面找到的权限对象、权限字段和值。

  2. 如下调整代码:

IF sy-subrc <> 0.
RAISE EXCEPTION TYPE cx_abap_invalid_value.
ENDIF.
AUTHORITY-CHECK
OBJECT '/LRN/CARR'
ID '/LRN/CARR' FIELD i_carrier_id
ID 'ACTVT'     FIELD '03'.
IF sy-subrc <> 0.
ENDIF.
  1. 如果用户没有请求的航空公司标识的显示权限,则引发异常 CX_ABAP_AUTH_CHECK_EXCEPTION

  2. 如下调整代码:

AUTHORITY-CHECK
OBJECT '/LRN/CARR'
ID '/LRN/CARR' FIELD i_carrier_id
ID 'ACTVT'     FIELD '03'.
IF sy-subrc <> 0.
RAISE EXCEPTION TYPE cx_abap_auth_check_exception.
ENDIF.
  1. 使用快速修复将异常 CX_ABAP_AUTH_CHECK_EXCEPTION 添加到**构造方法**定义的 RAISING 子句中。

  2. 在 RAISE EXCEPTION 语句中,单击 cx_abap_auth_check_exception 并按 Ctrl + 1。或者,选择具有语法警告的代码行左侧的灯泡图标。

  3. 从建议的快速修复列表中,选择添加引发声明

  4. 因此,**构造函数**方法的定义现在应如下所示:

METHODS constructor
IMPORTING
i_carrier_id TYPE /dmo/carrier_id
RAISING
cx_abap_invalid_value
cx_abap_auth_check_exception.
  1. 在全局类中,使用新异常 CX_ABAP_AUTH_CHECK_EXCEPTION 的 CATCH 块扩展 TRY…ENDTRY 控制结构。发布合适的文本以指示用户无权显示运输公司。

  2. 如下调整代码:

TRY.
DATA(carrier) = NEW lcl_carrier( i_carrier_id = c_carrier_id ).
out->write( name = `Carrier Overview`
data = carrier->get_output(  ) ).
CATCH cx_abap_invalid_value.
out->write( |Carrier { c_carrier_id } does not exist| ).
CATCH cx_abap_auth_check_exception.
out->write( |No authorization to display carrier { c_carrier_id }| ).
ENDTRY.
  1. 同样,在本地单元测试类的 class_setup 方法中扩展 TRY…ENDTRY 控制结构。使用与异常 CX_ABAP_INVALID_VALUE 的捕获块中相同的实施。

注意

这只是一个解决方法。稍后,在本课程中,您将了解如何处理同一捕获块中的多个异常。

  1. 如下调整代码:

TRY.
the_carrier = NEW lcl_carrier( i_carrier_id = some_flight_data-carrier_id ).
CATCH cx_abap_invalid_value.
cl_abap_unit_assert=>fail( `Unable to instantiate lcl_carrier` ).
CATCH cx_abap_auth_check_exception.
cl_abap_unit_assert=>fail( `Unable to instantiate lcl_carrier` ).
ENDTRY.
  1. 以控制台应用形式激活并测试全局类。确保您的代码在控制台上显示新文本:无权显示运输公司 UA

  2. Ctrl + F3

  3. F9

  4. 在全局类中,将本地常量 c_carrier_id 的值更改回 LH

  5. 切换到全局类标签。

  6. 如下调整代码:

*  CONSTANTS c_carrier_id TYPE /dmo/carrier_id VALUE 'UA'.
CONSTANTS c_carrier_id TYPE /dmo/carrier_id VALUE 'LH'.
  1. 以控制台应用形式激活并测试全局类。确保代码像以前一样显示承运商和航班详细信息。

  2. Ctrl + F3

  3. F9