2023年8月9日水曜日

直リンクでフォームを開く際にユーザー・レベルのチェックサムを使ってページを保護する

 特定のユーザーに電子メールなどの手段を使って編集フォームの直リンクを送付する際に、指定したユーザー以外のアクセスおよび、指定したユーザーでもURLで指定したデータのみ編集できるように限定します。直リンクのURLへのこのような保護を、ユーザー・レベルのチェックサムを付加することにより実現してみます。

以下より実装方法について紹介します。

アプリケーション作成ウィザードを起動します。アプリケーションの名前User Level Checksumとします。

今回のサンプルで使用する対話モード・レポートとページ・モードが標準のフォームページ作成ウィザードでないと作成できないため、このまま空のアプリケーションを作成します。

アプリケーションの作成をクリックします。

アプリケーションが作成されたら、ページ作成ウィザードを起動します。

ページの作成をクリックします。


対話モード・レポートを選択します。


対話モード・レポートの名前EMP Reportページ・モード標準です。フォーム・ページを含めるチェックを入れます。

フォーム・ページ名EMP Formとし、フォーム・ページ・モード標準を選択します。モーダル・ダイアログとドロワーの場合、ページを直接URLを指定して開くことはできません。モーダル・ダイアログとドロワーは必ず対話モード・レポートに重なる形で表示されるため、対話モード・レポートから開く必要があります。

データ・ソース表/ビューの名前EMPを指定します。

ナビゲーションはデフォルトから変更しません。

へ進みます。


主キー列1としてEMPNO (Number)を選択します。

ページの作成をクリックします。


以上で今回のサンプルを実装する準備ができました。

最初にフォームを開く際のURLを確認します。

対話モード・レポートを開き、任意の従業員を編集フォームで開きます。


フォームが開くので、URLを確認します。


URLのアプリケーションの別名以降は、次のようになっています。

/user-level-checksum/emp-form?p3_empno=7499&session=115160286541908&cs=3SMx19onQOI7QzYFv9fydpYl2NslAjSk_s70DVyc7JOBflP00q3GB7UV7HLHdM6vjBu_jPQvI-J1COuhPFYZNWA

/アプリケーション別名/ページ名?p3_empno=編集対象の従業員番号&session=セッションID&cs=チェックサム

例えばこのURLを電子メールに含めて送信しても、電子メールでURLを受け取った人は編集フォームを開くことができません。ページemp-formをAPEXセッション外から開けないように保護されている(ディープ・リンク無効になっている)ことと、ページ・アイテムP3_EMPNOを保護するために生成されているチェックサムが、同じAPEXセッション内にあるときに限り有効(セッション・ステート保護チェックサムが必要 - セッション・レベル)であるためです。

これから、電子メールでURLを受け取ったユーザーが編集フォームを開けるようにする設定を行います。

ページ・デザイナにてフォームのページEMP Formを開きます。

セキュリティディープ・リンク有効にします。直接フォームのページを開くことを許可します。


ページ・アイテムP3_EMPNOを選択します。

セキュリティセッション・ステート保護チェックサムが必要 - セッション・レベルからチェックサムが必要 - ユーザー・レベルに変更します。

これで、このフォームにアクセスするためのURLを生成したユーザーであれば、そのURLを使って(APEXセッションの有無に関わらず)フォームを開くことができるようになります。

URLの引数としてページ・アイテムP3_EMPNOに値が設定されるため、制限付き文字a-Z、0-9と空白の許可リストを選択し、制限なしよりは安全に配慮します。


以上で、従業員を指定してフォームを直接開くことができるようになりました。

対話モード・レポートを開き、任意の従業員の編集フォームを開きます。

ユーザー・レベルのチェックサムが生成されているため、このURLをコピーし別のブラウザで開くことができます。ユーザー認証を要求されるため、対話モード・レポートを開いたユーザーと同じユーザーでサインインする必要があります。


バッチでURLを生成する場合は、APEX_SESSION.CREATE_SESSIONを呼び出して、URLを開くユーザーでAPEXセッションを開始した上でURLを生成します。

直リンクのURLを生成するサンプルです。


ユーザーが電子メールに添付されたURLをクリックした場合、今までの設定では必ずユーザー認証が行われ、新規にセッションが開始します。ユーザーがすでにAPEXアプリケーションにサインイン済みで作業をしていると、そのセッションが無効になります。

ページ・プロパティのセッション管理セッションを再結合すべてのセッションに対して有効にすると、既存のAPEXセッションがあれば、そのセッションを利用します。そのため、再度ユーザー認証を要求されることが無くなります。


一般にセッションの再結合は、セキュリティ上問題が発生しないパブリック・ページに対してのみ設定します。セッションの再結合が有効になっているページは、ユーザー認証をせずにアクセスできるようになるためです。

今回の例では、ユーザー・レベルのチェックサムがURLに含まれています。別のユーザーで認証されたAPEXセッションに再結合したときは、URLにアクセスしてもチェックサムのエラーが発生しアクセスが禁止されます。そのため、セッションの再結合を有効にしてアプリケーションの利便性を上げるという選択肢を採用することができます。


ユーザー・レベルのチェックサムはセッション・レベルと異なり、有効期限がありません。今までに生成されたユーザー・レベルのチェックサム(を含むURL)を無効にするには、アプリケーション定義セキュリティセッション・ステート保護ブックマークの無効化を実行します。


ブックマークされたリンクの無効化をクリックして、今までに生成されたURLを無効にします。


ただし、この無効化はセッション・レベル、ユーザー・レベル、アプリケーション・レベルのすべてのチェックサムを無効にします。Oracle APEXは、個別のURLに含まれるチェックサムに限定して無効化する手段を提供していません。

この制限に対応するため、直リンクに有効期限を含めてみます。

直リンクの宛先となるページにページ・アイテムP3_UNTILを作成します。

タイプ非表示セッション・ステートストレージリクエストごと(メモリーのみ)とします。セキュリティセッション・ステート保護チェックサムが必要 - ユーザー・レベルを選択し、チェックサムの計算に含めるようにします。これでURLに現れる有効期限を直接編集するとチェックサムの不一致のエラーが発生するようになるため、勝手に有効期限を変えることができなくなります。念のため制限付き文字としてa-z、0-9と空白の許可リストを選択します。


有効期限を確認するプロセスを作成します。レンダリング前に実行します。

識別名前有効期限の確認とします。タイプとしてコードの実行を選択し、ソースPL/SQLコードとして以下を記述します。

サーバー側の条件タイプアイテムはNULLではないを選択し、アイテムとしてP3_UNTILを指定します。


直リンクの生成を行うコードは、以下のように変更します。有効期限を1分に設定しています。この他にも操作を一回だけ有効にするといった実装も、少々コードを変えることで実現できるでしょう。

リンクの有効期限が過ぎている場合は、ホーム・ページを開くようにしています。

今回の記事は以上になります。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/user-level-checksum.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。