権限チェックの実装

AUTHORITY-CHECK 命令の使用

Objective

After completing this lesson, you will be able to 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 文の使用方法

Authority-Check 文の使用方法については、このビデオを視聴してください。

権限チェックの実装

コードにより、ユーザに表示権限がないデータへのアクセスが許可されていることがわかりました。これを修正するには、最初に 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、## はグループ番号)。

    1. Project Explorer で、クラス /LRN/CL_S4D401_ITS_SEC_KEY を右クリックしてコンテキストメニューを開きます。

    2. コンテキストメニューから Duplicate.... を選択します。

    3. Package 項目にパッケージの名称を入力します。Name 項目に、ZCL_##_SOLUTION (## はグループ番号) と入力します。

    4. Next を選択します。

    5. 移送依頼を確認し、Finish を選択します。

  2. コピーを有効化します。

    1. Ctrl + F3 を押してクラスを有効化します。

タスク 2: 権限分析

データベーステーブル /LRN/CARRIER から開始して、権限のないアクセスから運送業者データを保護する CDS アクセス制御を見つけます。CDS アクセス制御を分析して、ユーザが運送業者データを照会するために必要な権限を確認します。

ステップ

  1. データベーステーブル /LRN/CARRIER の定義を照会します。

    1. Ctrl + Shift + A を押し、検索項目に /LRN/CARRIER と入力します。

    2. OK を選択します。

  2. このデータベーステーブルの使用先一覧を分析します。

    1. データベーステーブル /LRN/CARRIER の定義で、/lrn/carrier を右クリックし、使用先一覧取得を選択します。または、/lrn/carrier をクリックして Ctrl + Shift + G を押します。

    2. オブジェクトタイプ選択ダイアログで、少なくともオブジェクトタイプデータ定義が選択されていることを確認し、終了を選択します。

    3. エディタの下の検索ビューで、ファンネルアイコンを選択してフィルタダイアログを開きます。

    4. オブジェクトタイプ項目にカーソルを置き、Ctrl + Space を押して入力ヘルプダイアログを開きます。

    5. 候補リストから DDLS/DF (データ定義) を選択し、適用を選択します。

  3. CDS ビュー /LRN/I_CARRIERの使用先一覧を分析します。

    1. 検索ビューで、 /LRN/I_CARRIER (データ定義) を右クリックし、使用先一覧取得を選択します。または、/LRN/I_CARRIER (データ定義) をクリックし、Ctrl + Shift + G を押します。

    2. オブジェクトタイプ選択ダイアログで、少なくともオブジェクトタイプアクセス制御が選択されていることを確認し、終了を選択します。

    3. エディタの下にある検索ビューの該当対象が多すぎる場合は、ファンネルアイコンを選択してフィルタダイアログを開きます。オブジェクトタイプ項目にカーソルを置き、Ctrl + Space を押して入力ヘルプダイアログを開きます。候補リストから DCLS/DL (Access Control) を選択し、Apply を選択します。

  4. アクセス制御 /LRN/I_CARRIER の定義を開きます。

    1. 検索ビューで、 /LRN/I_CARRIER (アクセス制御) をダブルクリックします。

    2. 権限オブジェクト名は、機能 pfcg_auth の最初の入力パラメータです。

    3. その他の入力パラメータにより、権限オブジェクトの権限項目に値が指定されます。

  5. 権限オブジェクト /LRN/CARR の定義を開き、アクティビティ値の意味を分析します。

    1. Ctrl キーを押したまま、pfcg_auth 関数の呼出で /LRN/CARR をクリックします。

    2. 使用可能なアクティビティ値は、許可済アクティビティに一覧表示されます。

タスク 3: CDS アクセス制御の使用

ローカルクラス LCL_CARRIERコンストラクタメソッドで、データベーステーブル /LRN/CARRIER を CDS アクセス制御 /LRN/I_CARRIER によって保護されている CDS ビュー /LRN/I_CARRIER に置き換えます。コンストラクタ入力として異なる運送業者 ID を使用してコードをテストします。

ステップ

  1. ローカルクラス LCL_CARRIERコンストラクタメソッドの実装を開きます。

    1. グローバルクラス ZCL_##_SOLUTION のコードに戻ります。## は各自のグループ番号です。

    2. Outline ビューで ZCL_##_SOLUTIONLCL_CARRIER を展開し、CONSTRUCTOR をクリックします。

  2. SELECT 文を調整します。FROM 句で、データベーステーブル /LRN/CARRIER を上記の CDS ビューに置き換えます。

    1. コードを以下のように調整します。

      ABAP
      123
      SELECT SINGLE * FROM /lrn/carrier FROM /LRN/I_Carrier
  3. 構文エラーを修正します。テーブル項目名を対応する CDS ビューエレメント名に置き換えます。

    1. コードを以下のように調整します。

      ABAP
      1234567891011
      * 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 ).
  4. グローバルクラスをコンソールアプリとして有効化してテストします。

    1. Ctrl + F3 を押します。

    2. F9 を押します。

  5. グローバルクラスで、ローカル定数 c_carrier_id の値を UA に変更します。

    1. グローバルクラスタブに切り替えます。

    2. コードを以下のように調整します。

      ABAP
      12
      * CONSTANTS c_carrier_id TYPE /dmo/carrier_id VALUE 'LH'. CONSTANTS c_carrier_id TYPE /dmo/carrier_id VALUE 'UA'.
  6. グローバルクラスをコンソールアプリとして有効化してテストします。

    1. Ctrl + F3 を押します。

    2. F9 を押します。

タスク 4: AUTHORITY-CHECK 命令の実装

ローカルクラス LCL_CARRIERコンストラクタメソッドで、AUTHORITY-CHECK 命令を実装し、フライトキャリアが存在するものの、ユーザにこの航空会社に対する権限がない場合は、例外 CX_ABAP_AUTH_CHECK_EXCEPTION を発生させます。

ステップ

  1. ローカルクラス LCL_CARRIERコンストラクタメソッドの実装を開きます。

    1. エディタでグローバルクラス ZCL_##_SOLUTION が開いていることを確認します (## は各自のグループ番号)。

    2. Outline ビューで ZCL_##_SOLUTIONLCL_CARRIER を展開し、CONSTRUCTOR をクリックします。

  2. データベーステーブル /LRN/CARRIER から再度読み込むように SELECT 文を調整します。

    1. コードを以下のように調整します。

      ABAP
      1234567891011
      * 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 ).
  3. 読込アクセスが成功した場合、つまり例外 CX_ABAP_INVALID_VALUE が発生しなかった場合に実行される AUTHORITY-CHECK 命令を実装します。上記の権限オブジェクト、権限項目、および値を使用します。

    1. コードを以下のように調整します。

      ABAP
      123456789101112
      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.
  4. ユーザに要求された航空会社 ID の照会権限がない場合は、例外 CX_ABAP_AUTH_CHECK_EXCEPTION を発生させます。

    1. コードを以下のように調整します。

      ABAP
      12345678
      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.
  5. クイックフィックスを使用して、コンストラクタメソッドの定義の RAISING 句に例外 CX_ABAP_AUTH_CHECK_EXCEPTION を追加します。

    1. RAISE EXCEPTION 命令で、cx_abap_auth_check_exception をクリックして Ctrl + 1 を押します。または、構文警告が表示されているコード行の左側にある電球アイコンを選択します。

    2. 提案されたクイックフィックスの一覧から、Add raising declaration を選択します。

    3. その結果、コンストラクタメソッドの定義は以下のようになります。

      ABAP
      123456
      METHODS constructor IMPORTING i_carrier_id TYPE /dmo/carrier_id RAISING cx_abap_invalid_value cx_abap_auth_check_exception.
  6. グローバルクラスで、新規例外 CX_ABAP_AUTH_CHECK_EXCEPTION の CATCH ブロックを使用して TRY ... ENDTRY 制御構造を拡張します。ユーザに航空会社を照会する権限がないことを示す適切なテキストを発行します。

    1. コードを以下のように調整します。

      ABAP
      123456789
      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.
  7. 同様に、ローカルユニットテストクラスの class_setup メソッドで TRY ... ENDTRY 制御構造を拡張します。例外 CX_ABAP_INVALID_VALUE の捕捉ブロックと同じ実装を使用します。

    注記

    これは回避策にすぎません。このコースの後半では、同じ Catch ブロックで複数の例外を処理する方法について学習します。
    1. コードを以下のように調整します。

      ABAP
      1234567
      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.
  8. グローバルクラスをコンソールアプリとして有効化してテストします。コンソールに新しいテキスト (航空会社 UA を表示する権限なし) がコードに表示されていることを確認します。

    1. Ctrl + F3 を押します。

    2. F9 を押します。

  9. グローバルクラスで、ローカル定数 c_carrier_id の値を LH に戻します。

    1. グローバルクラスタブに切り替えます。

    2. コードを以下のように調整します。

      ABAP
      12
      * CONSTANTS c_carrier_id TYPE /dmo/carrier_id VALUE 'UA'. CONSTANTS c_carrier_id TYPE /dmo/carrier_id VALUE 'LH'.
  10. グローバルクラスをコンソールアプリとして有効化してテストします。コードに以前と同様に航空会社およびフライト詳細が表示されていることを確認します。

    1. Ctrl + F3 を押します。

    2. F9 を押します。