2021年1月9日土曜日

ORDS RESTfulサービスをOracle APEXのセッションで認証する

Twitterを見ていたら、このツィートへのKris Riceの返信として、ORDSのRESTfulサービスでOracle APEXのセッションを引き継げるとコメントしていました。

これは初耳だったので、自分でも確認してみました。

こちらの記事 - Oracle APEXでWebコンポーネント扱う - で作成したRESTfulサービスを保護した上で、アプリケーションを改変してみます。

RESTfulサービスの保護


RESTfulサービス自体はサンプルのoracle.example.hrです。このモジュールを対象として権限を追加します。マニュアルの記載箇所はこちらです。

SQLワークショップよりRESTfulサービスを開いて、左ペインのツリーから権限を選択します。右側のペインにORDSの権限として、一覧ページが表示されます。権限の作成を実行します。

名前、タイトルは任意です。ここではそれぞれ、名前をモジュール名と同じoracle.example.hrタイトルHR Accessとしています。

ロールとして、RESTful Servicesを選択します。そして、保護されたモジュールとして、oracle.example.hrを選択し、権限を作成します。


以上でRESTfulサービスの保護は完了です。

最初の例題で使用しているORDSテンプレート定義(employees/)の完全なURLを確認し、そのURLをブラウザから呼び出して、保護の状態を確認します。


URLにアクセスすると、401 Unauthrized が返されます。



アプリケーションの改変


保護されたRESTfulサービスへアクセスする際に、HTTPヘッダーとしてApex-Sessionを与えます。形式は以下です。

Apex-Session: アプリケーションID,セッションID

Webコンポーネントの記事で作成したアプリケーションをアプリケーション・ビルダーで開き、共有コンポーネント静的アプリケーション・ファイルを開きます。Edit Filesより、すでに作成済みのemployee-info.jsを選択します。


fetchの部分を、リクエストのヘッダーとしてApex-Sessionを含めるよう、以下に変更します。
    fetch('https://apex.oracle.com/pls/apex/あなたのWS/hr/employees/' + this.getAttribute('empno'),
      {
        "method": "GET",
        "headers": {
          "Apex-Session": this.getAttribute('appid') + "," + this.getAttribute('sessid')
        }
      }
    )

アプリケーションIDおよびセッションIDは、employee-info要素の属性のappidsessidとして渡します。

静的コンテンツのソースには、以下のようにappid、sessidを追加します。

<employee-info empno="7839" appid="&APP_ID." sessid="&APP_SESSION."></employee-info>


動的アクションの記載は、以下のようにappid、sessidを追加します。

$('#employee_data_container').append('<employee-info empno="' + empNo + '" appid="&APP_ID." sessid="&APP_SESSION."></employee-info>');


以上でアプリケーション側の変更も完了です。アプリケーションを実行すると、RESTfulサービスを保護する以前と同様に動作することが確認できます。

最後にKris Riceが、以下のSQLを実行していました。

select :current_user from dual

引き渡されたOracle APEXのセッションの認証ユーザー名(APP_USERに該当)が:current_userで取得できるとのこと。結果を見るとユーザー名が小文字になっていて、大抵の場合、大文字だけになるOracle APEX側のAPP_USER置換文字列とは若干異なるもようです。この点は要注意です。