10 アプリケーション・コンテキストを使用したユーザー情報の取得

アプリケーション・コンテキストにはユーザーIDが格納されており、これに基づいてデータベースのデータにユーザーがアクセスできるかを否かを決定できます。

10.1 アプリケーション・コンテキストについて

アプリケーション・コンテキストには、ユーザーがデータに対して保持するアクセスを制御する場合に多くのメリットがあります。

10.1.1 アプリケーション・コンテキストとは

アプリケーション・コンテキストとは、Oracle Databaseがメモリーに格納する名前と値のペアです。

コンテキストには、ネームスペースと呼ばれるラベル(たとえば、従業員IDを取得するアプリケーション・コンテキストにはempno_ctx)があります。このコンテキストにより、Oracle Databaseは認証中にデータベース・ユーザーと非データベース・ユーザーに関する情報を入手できます。

コンテキスト内は名前と値のペア(結合配列)です。名前は、値を保持するメモリー内の場所を指定します。アプリケーションはアプリケーション・コンテキストを使用して、ユーザーに関するセッション情報(ユーザーIDまたは他のユーザー固有の情報など)またはクライアントIDにアクセスして、その情報をデータベースに安全に引き渡すことができます。

この情報を使用して、ユーザーがアプリケーションを通じてデータにアクセスできるようにしたりアクセスできないようにできます。アプリケーション・コンテキストを使用して、データベース・ユーザーと非データベース・ユーザーの両方を認証できます。

10.1.2 アプリケーション・コンテキストの構成要素

アプリケーション・コンテキストには2つのコンポーネントがあり、名前と値のペアを構成します。

これらのコンポーネントは次のとおりです。

  • 名前。値に関連付けられている属性セットの名前を示します。たとえば、empno_ctxアプリケーション・コンテキストは従業員IDをHR.EMPLOYEES表から取得する場合、名前をemployee_idにすることができます。

  • 値。属性により設定される値を示します。たとえば、empno_ctxアプリケーション・コンテキストでは、HR.EMPLOYEES表から従業員IDを取得する場合、このIDの値を設定する、emp_idと呼ばれる値を作成できます。

アプリケーション・コンテキストは、データベース・セッション中にアクセスされる情報を保持するグローバル変数と考えてください。セキュア・アプリケーション・コンテキストの値を設定するには、DBMS_SESSION.SET_CONTEXTプロシージャを使用するPL/SQLパッケージ・プロシージャを作成する必要があります。実際、コンテキストがINITIALIZED EXTERNALLYまたはINITIALIZED GLOBALLYとマークされていない場合は、事実上、この方法がアプリケーション・コンテキスト値を設定できる唯一の方法となります。アプリケーション・コンテキスト属性には、アプリケーション・コンテキストの作成時ではなく、実行時に値を割り当てることができます。ユーザーではなくトラステッド・プロシージャによって値が割り当てられるため、これはセキュア・アプリケーション・コンテキストと呼ばれます。クライアント・セッション・ベースのアプリケーション・コンテキストの場合、Oracle Call Interface(OCI)コールを使用してアプリケーション・コンテキストを設定することもできます。

10.1.3 アプリケーション・コンテキストの値の格納場所

Oracle Databaseではアプリケーション・コンテキスト値が保護データ・キャッシュに格納されます。

このキャッシュはユーザー・グローバル領域(UGA)またはシステム("共有"と呼ばれる場合もある)グローバル領域(SGA)にあります。格納されたアプリケーション・コンテキストの値はセッション中に取得されます。アプリケーション・コンテキストには、このデータ・キャッシュ内の値が格納されるため、アプリケーションのパフォーマンスが向上します。アプリケーション・コンテキストは単独で使用でき、Oracle Virtual Private Databaseポリシーまたはその他のファイングレイン・アクセス制御ポリシーと併用することもできます。

10.1.4 アプリケーション・コンテキストを使用する利点

ほとんどのアプリケーションには、アプリケーション・コンテキストに使用可能なある種の情報が含まれています。

たとえば、ORDER_NUMBER列とCUSTOMER_NUMBER列を備えた表を使用する受注管理アプリケーションでは、それらの列の値をセキュリティ属性として使用して、顧客によるアクセスをその顧客のIDに基づいて顧客自身の注文のみに制限できます。

アプリケーション・コンテキストは、次の目的で使用されます。

  • ファイングレイン・アクセス・コントロールの規定(Oracle Virtual Private Databaseポリシーなどで)

  • 複数層環境でのユーザー識別情報の保持

  • アプリケーションに対する強力なセキュリティの規定(アプリケーション・コンテキストはユーザーではなくトラステッド・プロシージャによって制御されるため)

  • アプリケーションがファイングレイン監査やPL/SQL条件文またはループで使用する際に必要な属性に対して、保護データ・キャッシュとしての機能を果すことによるパフォーマンスの向上

    このキャッシュによって、これらの属性が必要になるたびにデータベースに問い合せるというオーバーヘッドが軽減されます。アプリケーションはセッション・データを表から繰り返し取得する必要がなく、このデータがアプリケーション・コンテキストによってキャッシュに格納されるため、アプリケーションのパフォーマンスが大幅に向上します。

  • アプリケーションで定義、変更およびアクセスできる名前と値のペアの保持領域として機能

10.1.5 エディションがアプリケーション・コンテキストの値に与える影響

Oracle Databaseでは、アプリケーション・コンテキスト・パッケージの影響を受けるすべてのエディションでアプリケーション・コンテキストが設定されます。

アプリケーション・コンテキストで設定される値は、アプリケーション・コンテキストが影響するすべてのエディションで表示されます。データベース内のすべてのエディション、およびそれが使用可能であるかどうかを検索するには、ALL_EDITIONSデータ・ディクショナリ・ビューを問い合せます。

関連項目:

エディションの詳細は、『Oracle Database開発ガイド』を参照してください。

10.1.6 マルチテナント環境でのアプリケーション・コンテキスト

マルチテナント環境のどこでアプリケーションを作成するかによって、アプリケーション・コンテキストを作成する場所が決まります。

アプリケーション・ルートまたはCDBルートにアプリケーションがインストールされると、そのアプリケーションはアプリケーション・コンテナまたはシステム・コンテナおよび関連付けられたアプリケーションPDBからアクセスできるようになります。そのルートで共通アプリケーション・コンテキストを作成する必要があります。

アプリケーション・コンテナで使用する共通アプリケーション・コンテキストを作成する場合は、次の点に注意してください。

  • マルチテナント環境でアプリケーション・コンテキストを作成するには、CREATE CONTEXT SQL文でCONTAINER句を設定します。たとえば、アプリケーション・ルートで共通アプリケーション・コンテキストを作成するには、CONTAINERALLに設定してCREATE CONTEXTを実行する必要があります。PDBでアプリケーション・コンテキストを作成するには、CONTAINERCURRENTに設定します。

  • ローカル・アプリケーション・コンテキストと共通アプリケーション・コンテキストに同じ名前を使用することはできません。既存のアプリケーション・コンテキストの名前は、次の問合せを実行して検索できます。

    SELECT OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_TYPE ='CONTEXT';
  • 共通アプリケーション・コンテキストを管理するために作成するPL/SQLパッケージは、共通PL/SQLパッケージであることが必要です。つまり、それがアプリケーション・ルートまたはCDBルートに存在する必要があります。特定のPDBのアプリケーション・コンテキストを作成する場合、関連付けられたPL/SQLパッケージをそのPDBに格納する必要があります。

  • 共通アプリケーション・コンテキストのアプリケーション・コンテナまたはシステム・コンテナから共通セッション・アプリケーション・コンテキストの下に設定した名前と値のペアは、共通ユーザーが異なるコンテナにアクセスする場合、他のアプリケーション・コンテナまたはシステム・コンテナからアクセスできません。

  • アプリケーション・コンテナまたはシステム・コンテナから共通グローバル・アプリケーション・コンテキストの下に設定した名前と値のペアは、同じユーザー・セッションの同じコンテナ内の場合にかぎりアクセスできます。

  • アプリケーションは、アプリケーション・ルート、CDBルートまたはPDBのいずれに存在していても、アプリケーション・コンテキストの値を取得できます。

  • CDBまたはアプリケーション・コンテナへのPDBの接続操作中、共通アプリケーション・コンテキストの名前がPDBのローカル・アプリケーション・コンテキストの名前と競合する場合は、PDBを制限モードでオープンする必要があります。データベース管理者は、PDBを通常モードでオープンする前に、競合を修正する必要があります。

  • 切断操作中、共通アプリケーション・コンテキストはその共通セマンティクスを維持することで、後にそのPDBが同じ名前の共通アプリケーション・コンテキストがある別のCDBに接続する場合、引き続き共通オブジェクトのように動作します。PDBが同じ共通アプリケーション・コンテキストが存在しないアプリケーション・コンテナまたはシステム・コンテナに接続する場合、そのPDBはローカル・オブジェクトのように動作します。

アプリケーション・コンテキストがローカル・アプリケーション・コンテキストであるかアプリケーションの共通アプリケーション・コンテキストであるかを確認するには、DBA_CONTEXTまたはALL_CONTEXTデータ・ディクショナリ・ビューのSCOPE列を問い合せます。

10.2 アプリケーション・コンテキストの種類

アプリケーション・コンテキストには、3種類の一般的なカテゴリがあります。

カテゴリは次のとおりです。

  • データベース・セッション・ベースのアプリケーション・コンテキスト。このタイプのアプリケーション・コンテキストは、データベース・ユーザー・セッション(つまりUGA)のキャッシュに格納されているデータを取得します。データベース・セッション・ベースのアプリケーション・コンテキストは、3つのカテゴリに分類されます。

    • ローカルで初期化。ユーザーのセッションに対してアプリケーション・コンテキストをローカルで初期化します。

    • 外部で初期化。Oracle Call Interface(OCI)アプリケーション、ジョブ・キュー・プロセスまたは接続ユーザーのデータベース・リンクからアプリケーション・コンテキストを初期化します。

    • グローバルに初期化。LDAPディレクトリなどの集中格納場所から属性と値を使用します。

    このタイプのアプリケーション・コンテキストについては、「データベース・セッション・ベースのアプリケーション・コンテキストの使用」を参照してください。

  • グローバル・アプリケーション・コンテキスト。このタイプは、システム・グローバル領域(SGA)に格納されるデータを取得するため、3層アーキテクチャの中間層アプリケーションなど、セッションを使用しないアプリケーションに対して使用できます。グローバル・アプリケーション・コンテキストは、セッション・コンテキストをセッション間で、たとえば接続プールの実装を通じて共有する場合に便利です。

    このタイプについては、「グローバル・アプリケーション・コンテキスト」を参照してください。

  • クライアント・セッション・ベースのアプリケーション・コンテキスト。このタイプのアプリケーション・コンテキストは、クライアント側のOracle Call Interface関数を使用してユーザー・セッション・データを設定し、次に、必要なセキュリティ・チェックを実行してユーザー・アクセスを制限します。

    このタイプについては、「クライアント・セッション・ベースのアプリケーション・コンテキストの使用」を参照してください。

表10-1に、異なる種類のアプリケーション・コンテキストの要約を示します。

表10-1 アプリケーション・コンテキストの種類

アプリケーション・コンテキストの種類 UGAへの格納 SGAへの格納 接続ユーザー・データベース・リンクのサポート ユーザーのアプリケーション・コンテキストの集中保管のサポート セッションを使用しない複数層アプリケーションのサポート

ローカルで初期化されるデータベース・セッション・ベースのアプリケーション・コンテキスト

はい

いいえ

いいえ

いいえ

いいえ

外部で初期化されるデータベース・セッション・ベースのアプリケーション・コンテキスト

はい

いいえ

はい

いいえ

いいえ

グローバルに初期化されるデータベース・セッション・ベースのアプリケーション・コンテキスト

はい

いいえ

いいえ

はい

いいえ

グローバル・アプリケーション・コンテキスト

いいえ

はい

いいえ

いいえ

はい

クライアント・セッション・ベースのアプリケーション・コンテキスト

はい

いいえ

はい

いいえ

はい

10.3 データベース・セッション・ベースのアプリケーション・コンテキストの使用

データベース・セッション・ベースのアプリケーション・コンテキストを使用すると、ユーザーのセッション・ベースの情報を取得できます。

10.3.1 データベース・セッション・ベースのアプリケーション・コンテキストについて

データベース・セッション・ベースのアプリケーション・コンテキストで、データベース・ユーザーのセッション情報を取得します。

このタイプのアプリケーション・コンテキストは、Oracle Database内でPL/SQLプロシージャを使用し、管理の対象となるデータを取得、設定および保護します。

データベース・セッション・ベースのアプリケーション・コンテキストは、Oracle Databaseの中で完全管理されます。Oracle Databaseが値を設定し、ユーザーがセッションを終了すると、キャッシュに保管されたアプリケーション・コンテキスト値を自動的にクリアします。ユーザー接続が異常終了すると(たとえば停電)、PMONバックグラウンド・プロセスはアプリケーション・コンテキスト・データをクリーン・アップします。アプリケーション・コンテキストをキャッシュから消去する必要はありません。

アプリケーション・コンテキストをOracle Databaseで管理する利点は、アプリケーション・コンテキストを集中管理できる点です。このデータベースにアクセスするアプリケーションは、このアプリケーション・コンテキストを使用して、そのアプリケーションに対するユーザーのアクセスを許可または防止する必要があります。これによって、パフォーマンス向上とセキュリティ強化の両方の利点が得られます。

ノート:

ユーザーがアプリケーション・ユーザー(つまり、データベースに存在しないユーザー)の場合は、グローバル・アプリケーション・コンテキストの使用を考慮してください。

10.3.2 データベース・セッション・ベースのアプリケーション・コンテキストのコンポーネント

データベース・セッション・ベースのアプリケーション・コンテキストは、コンテキストのデータを取得および設定して、ユーザーがログインするときにこのコンテキストを設定します。

データベース・セッション・ベースのアプリケーション・コンテキストを作成して使用するには、アプリケーション・コンテキスト、データの取得とコンテキストの設定を実行するプロシージャ、およびユーザーのログイン時にコンテキストを設定する手段の3つのコンポーネントを使用する必要があります。

  • アプリケーション・コンテキスト。アプリケーション・コンテキストを作成するには、CREATE CONTEXT SQL文を使用します。この文は、アプリケーション・コンテキスト(ネームスペース)名を設定し、セッション・データを取得してアプリケーション・コンテキストを設定するように設計されたPL/SQLプロシージャに対して、その名前を関連付けます。

  • データの取得とコンテキストの設定を実行するPL/SQLプロシージャ。このプロシージャで実行する必要があるタスクの概要については、データベース・セッション・ベースのアプリケーション・コンテキストを管理するパッケージについてを参照してください。理想的には、必要に応じて他のプロシージャ(タスクのエラー・チェックなど)を挿入できるように、このプロシージャは1つのパッケージ内に作成します。

  • ユーザーのログイン時にアプリケーション・コンテキストを設定する手段。アプリケーション・コンテキストを使用するアプリケーションにログインするユーザーは、そのアプリケーション・コンテキストを設定するPL/SQLパッケージを実行する必要があります。そのためには、ユーザーがログインするたびに起動するログイン・トリガーを使用するか、この機能をアプリケーションに埋め込むことができます。

ローカルで初期化されるデータベース・セッション・ベースのアプリケーション・コンテキストの作成方法と使用方法は、例: データベース・セッション・ベースのアプリケーション・コンテキストの作成と使用を参照してください。

さらに、セッション・ベースのアプリケーション・コンテキストは、外部で、またはグローバルに初期化できます。いずれの場合も、コンテキスト情報はユーザー・セッションに格納されます。

10.3.3 データベース・セッション・ベースのアプリケーション・コンテキストの作成

データベース・セッション・ベースのアプリケーション・コンテキストは、ユーザーのセッション情報を格納する名前付きのオブジェクトです。

10.3.3.1 データベース・セッション・ベースのアプリケーション・コンテキストの作成について

ユーザー作成のネームスペースを使用して、データベース・ユーザー・セッション(UGA)には、セッション・ベースのアプリケーション・コンテキストが格納されます。

各アプリケーション・コンテキストには一意の属性が必要で、1つのネームスペースに属している必要があります。つまり、コンテキスト名は、スキーマ内のみでなくデータベース内でも一意である必要があります。

アプリケーション・コンテキストを作成するには、CREATE ANY CONTEXTシステム権限が必要です。アプリケーション・コンテキストを削除する場合は、DROP CONTEXT文を使用するためにDROP ANY CONTEXT権限が必要になります。

アプリケーション・コンテキストの所有権については、CREATE ANY CONTEXT権限とDROP ANY CONTEXT権限を付与されたユーザーがそのアプリケーション・コンテキストを作成および削除できた場合でも、SYSスキーマが所有しています。Oracle Databaseは、作成したスキーマ・アカウントにコンテキストを関連付けますが、このユーザーを削除した場合、コンテキストはそれでもSYSスキーマの中に存在します。ユーザーSYSであれば、アプリケーション・コンテキストを削除できます。

既存のアプリケーション・コンテキストの名前は、次の問合せを実行して検索できます。

SELECT OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_TYPE ='CONTEXT';
10.3.3.2 データベース・セッション・ベースのアプリケーション・コンテキストの作成

CREATE CONTEXT SQL文を使用して、データベース・セッション・ベースのアプリケーション・コンテキストを作成できます。

データベース・セッション・ベースのアプリケーション・コンテキストを作成する場合、そのアプリケーション・コンテキストのネームスペースを作成し、ユーザーのセッション情報を保持する名前と値のペアを管理するPL/SQLパッケージとそのネームスペースを関連付ける必要があります。PL/SQLパッケージは、コンテキストの作成時には不要ですが、実行時には存在している必要があります。

  • データベース・セッション・ベースのアプリケーション・コンテキストを作成するには、CREATE CONTEXT SQL文を使用します。

    たとえば:

    CREATE CONTEXT empno_ctx USING set_empno_ctx_pkg CONTAINER = CURRENT;
    

この例では、次のようになります。

  • empno_ctxはコンテキスト・ネームスペースです。

  • set_empno_ctx_pkgは、そのempno_ctxネームスペースの属性を設定するパッケージです(コンテキストの作成時には不要です)。このアプリケーション・コンテキストで使用可能なパッケージの作成方法の例は、ステップ3: セッション・データを取得してアプリケーション・コンテキストを設定するパッケージの作成を参照してください。

  • CONTAINERは、現在のPDBでアプリケーション・コンテキストを作成します。アプリケーション・ルートまたはCDBルートでアプリケーション・コンテキストを作成するには、CONTAINERALLに設定する必要があります。

コンテキストを作成するときは、そのコンテキストの名前/値の属性をCREATE CONTEXT文に設定しないでください。かわりに、これらは、アプリケーション・コンテキストに関連付けるPL/SQLパッケージに設定してください。これは、不正なユーザーによって、適切な属性の検証なしにコンテキスト属性が変更されないようにするためです。このパッケージがアプリケーション・コンテキストと同じコンテナにあることを確認してください。たとえば、アプリケーション・コンテキストをPDBに作成した場合、PL/SQLパッケージはそのPDBに存在する必要があります。

ノート:

CLIENTCONTEXTというコンテキストは作成できません。これは、クライアント・セッション・ベースのアプリケーション・コンテキストで使用される予約語です。このタイプのアプリケーション・コンテキストの詳細は、クライアント・セッション・ベースのアプリケーション・コンテキストの使用を参照してください。

10.3.3.3 複数のアプリケーションのデータベース・セッション・ベースのアプリケーション・コンテキスト

各アプリケーションには、独自の属性を持つアプリケーション・コンテキストを作成できます。

たとえば、General Ledger(一般会計)、Order Entry(受注管理)およびHuman Resources(人事管理)という3つのアプリケーションがあるとします。

これらの各アプリケーションには、異なる属性を指定できます。

  • 受注管理アプリケーション・コンテキストには、CUSTOMER_NUMBER属性を指定できます。

  • 一般会計アプリケーション・コンテキストには、SET_OF_BOOKS属性とTITLE属性を指定できます。

  • 人事管理アプリケーション・コンテキストには、ORGANIZATION_IDPOSITIONCOUNTRYの各属性を指定できます。

属性がアクセスするデータは、アプリケーション外の表に保管されます。たとえば、受注管理アプリケーションではOE.CUSTOMERSという名前の表が使用されており、この中のCUSTOMER_NUMBER列にはCUSTOMER_NUMBER属性のデータが入ります。いずれの場合にも、アプリケーション・コンテキストを厳密なセキュリティ・ニーズに適用できます。

10.3.4 データベース・セッション・ベースのアプリケーション・コンテキストを設定するためのパッケージの作成

PL/SQLパッケージを使用し、セッション情報を取得してアプリケーション・コンテキストの名前と値の属性を設定できます。

10.3.4.1 データベース・セッション・ベースのアプリケーション・コンテキストを管理するパッケージについて

これは、アプリケーション・コンテキストにより示されたセッション・データを管理するプロシージャを定義します。

このパッケージは、通常、セキュリティ管理者のスキーマに作成されます。パッケージでは、次のタスクを実行する必要があります。

  • セッション情報の取得。ユーザー・セッション情報の取得には、SYS_CONTEXT SQL関数を使用できます。このSYS_CONTEXT関数は、コンテキストのネームスペースに関連付けられているパラメータの値を戻します。この関数は、SQL文とPL/SQL文の両方で使用できます。通常は、組み込まれているUSERENVネームスペースを使用してユーザーのセッション情報を取得します。SYS_SESSION_ROLESネームスペースを使用して、セッションに対して指定したロールが現在有効化されているかどうかを示すこともできます。

  • CREATE CONTEXTで作成したアプリケーション・コンテキストの名前/値の属性の設定。アプリケーション・コンテキストの名前/値の属性の設定には、DBMS_SESSION.SET_CONTEXTプロシージャを使用できます。この名前/値の属性には、ユーザーID、IPアドレス、認証モード、アプリケーション名などの情報を格納できます。設定した属性の値は、再設定するまで、またはユーザーがセッションを終了するまでそのまま残ります。次のことに注意してください。

    • ネームスペース内のパラメータの値がすでに設定されている場合は、SET_CONTEXTによってこの値が上書きされます。

    • コンテキストの値が変更された場合、その内容はただちに反映され、SYS_CONTEXTファンクションによって値を取得する後続のコールでは、最新の値が戻されます。

  • ユーザーによる実行。パッケージを作成した後、ログインする場合ユーザーはそのパッケージを実行する必要があります。ユーザーがログインするときパッケージを自動的に実行するためのログイン・トリガーを作成するか、この機能をアプリケーションに埋め込むことができます。アプリケーション・コンテキスト・セッション値はユーザーがセッションを終了すると自動的にクリアされるので、セッション・データを手動で削除する必要はありません。

プロシージャはトラステッド・プロシージャであることに注意してください。ユーザーが自分独自のアプリケーション・コンテキスト属性値を設定できないように設計されています。ユーザーはプロシージャを実行しますが、プロシージャがアプリケーション・コンテキスト値を設定します、ユーザーではありません。

関連項目:

10.3.4.2 SYS_CONTEXTファンクションを使用したセッション情報の取得

SYS_CONTEXTファンクションを使用して、アプリケーション・コンテキストのセッション情報を取得できます。

SYS_CONTEXT関数には、ログインしたユーザーのカレント・セッションを表すデフォルト・ネームスペースUSERENVがあります。SYS_CONTEXTを使用すると、ユーザー・ホスト・コンピュータID、ホストIPアドレス、オペレーティング・システム・ユーザー名など、ユーザーに関する様々な種類のセッション・ベースの情報を取得できます。セッション・データを設定ではなく、取得するにはUSERENVのみを使用することに注意してください。事前定義の属性は、『Oracle Database SQL言語リファレンス』のPL/SQLファンクションの説明でリストされています。

  • セッション情報を取得するには、ネームスペースとパラメータを設定し、オプションでSYS_CONTEXTファンクションの長さの値を設定します。

    たとえば:

    SYS_CONTEXT ('USERENV','HOST')
    

PL/SQLファンクションのSYS_CONTEXTの構文は、次のとおりです。

SYS_CONTEXT ('namespace','parameter'[,length])

詳細は、次のとおりです。

  • namespaceはアプリケーション・コンテキストの名前です。文字列、または文字列として評価される式を指定できます。SYS_CONTEXTファンクションは、現時点でコンテキストのネームスペースに関連付けられているパラメータの値を戻します。ネームスペース内のパラメータの値がすでに設定されている場合は、SET_CONTEXTによってこの値が上書きされます。

  • parameterは、namespaceアプリケーション・コンテキスト内のパラメータです。この値には、文字列または式を指定できます。

  • lengthは戻り型のデフォルト最大サイズ(256バイト)ですが、最大で4000バイトの値を指定して長さを変更できます。NUMBERデータ型の値を入力するか、NUMBERに明示的に変換できる値を入力します。SYS_CONTEXT戻り型のデータ型はVARCHAR2です。この設定はオプションです。

ノート:

USERENVアプリケーション・コンテキスト・ネームスペースは、Oracle Databaseの以前のリリースで提供されていたUSERENV関数にかわる機能です。

10.3.4.3 SYS_CONTEXT設定の確認

DUAL表に格納されるSYS_CONTEXT設定を確認できます。

DUAL表はデータ・ディクショナリ内の小さい表で、既知の結果を保証するためにOracle Databaseおよびユーザーが記述したプログラムから参照できます。この表には、DUMMYという列と、値Xが格納されている行があります。

  • SYS_CONTEXT設定を確認するには、DUAL表に対してSELECT SQL文を発行します。

たとえば、ログインしたホスト・コンピュータを確認する場合、EMP_USERSの下のSHOBEEN_PCホスト・コンピュータにログインしたと想定しています。

SELECT SYS_CONTEXT ('USERENV', 'HOST') FROM DUAL;

SYS_CONTEXT(USERENV,HOST)
-------------------------
EMP_USERS\SHOBEEEN_PC
10.3.4.4 SYS_CONTEXTでの動的SQL

指定した問合せを実行する間にポリシーの変更が予想されるセッション中は、その問合せに動的SQLを使用する必要があります。

静的SQLと動的SQLでは文の解析方法が異なるため、必ず動的SQLを使用してください。

  • 静的SQL文はコンパイル時に解析されます。パフォーマンス上の理由から実行時には再解析されません。

  • 動的SQL文は、実行されるたびに解析されます。

SQL文のコンパイル時にはポリシーAを規定し、その後、ポリシーBに変更して文を実行する場合を考えてみます。静的SQLでは、ポリシーAが規定されたままです。文はコンパイル時に解析されますが、実行時には再解析されません。動的SQLでは、文は実行時に解析されるため、ポリシーBへの切替えが有効となります。

たとえば、次のポリシーを考えてみます。

EMPLOYEE_NAME = SYS_CONTEXT ('USERENV', 'SESSION_USER')

ポリシーEMPLOYEE_NAMEは、データベース・ユーザー名と一致しています。Oracle Virtual Private DatabaseではSQL述語の形で表され、述語はポリシーとみなされます。述語が変更された場合、正しい結果を生成するために文を再度解析する必要があります。

10.3.4.5 パラレル問合せでのSYS_CONTEXT

パラレル問合せに埋め込まれているSQL関数内でSYS_CONTEXTを使用すると、この関数にアプリケーション・コンテキストが挿入されます。

ユーザーIDを5に設定する、SQL文内のユーザー定義関数を考えてみます。

CREATE FUNCTION set_id 
 RETURN NUMBER IS
BEGIN
 IF SYS_CONTEXT ('hr', 'id') = 5
   THEN RETURN 1; ELSE RETURN 2;
 END IF;
END;

次の文を考えてみます。

SELECT * FROM emp WHERE set_id( ) = 1;

この文をパラレル問合せとして実行すると、アプリケーション・コンテキスト情報を含むユーザー・セッションはパラレル実行サーバー(問合せ子プロセス)に伝播されます。

10.3.4.6 データベース・リンクでのSYS_CONTEXT

SYS_CONTEXTファンクションはデータベース・リンクと一緒に使用できます。

ユーザー・セッション内のSQL文にデータベース・リンクが含まれている場合は、そのデータベース・リンクのホスト・コンピュータでSYS_CONTEXT関数が実行され、そのホスト・コンピュータにあるコンテキスト情報が取得されます。

リモートのPL/SQLプロシージャ・コールがデータベース・リンクで実行されている場合は、そのプロシージャ内部のすべてのSYS_CONTEXT関数が、そのリンクの宛先データベースで実行されます。

この場合、データベース・リンクの宛先サイトで使用できるのは、外部で初期化されたアプリケーション・コンテキストのみです。セキュリティ上の理由から、データベース・リンクの開始サイトから宛先サイトに伝播されるのは、外部で初期化されたアプリケーション・コンテキストのみです。

10.3.4.7 セッション情報を設定するためのDBMS_SESSION.SET_CONTEXT

SYS_CONTEXTでユーザーのセッション・データを取得した後、ユーザー・セッションからアプリケーション・コンテキスト値を設定できます。

コンテキスト値を設定するには、DBMS_SESSION.SET_CONTEXTプロシージャを使用します。DBMS_SESSION PL/SQLパッケージに対するEXECUTE権限を所有している必要があります。

DBMS_SESSION.SET_CONTEXTの構文は、次のとおりです。

DBMS_SESSION.SET_CONTEXT (
   namespace VARCHAR2,
   attribute VARCHAR2,
   value     VARCHAR2,
   username  VARCHAR2,
   client_id VARCHAR2);

詳細は、次のとおりです。

  • namespaceは、設定するアプリケーション・コンテキストのネームスペース(30バイトに制限)です。たとえば、custno_ctxという名前のネームスペースを使用していた場合は、次のように指定します。

    namespace => 'custno_ctx',
    
  • attributeは、設定するアプリケーション・コンテキストの属性(30バイトに制限)です。たとえばcustno_ctxネームスペースのctx_attrib属性を作成する場合は、次のようになります。

    attribute => 'ctx_attrib',
    
  • valueは、設定するアプリケーション・コンテキストの値(4000バイトに制限)です。通常、これはSYS_CONTEXT関数で取得されて変数に格納された値です。たとえば:

    value => ctx_value,
    
  • usernameは、アプリケーション・コンテキストのデータベース・ユーザー名属性です。デフォルトはNULLで、すべてのユーザーにセッションへのアクセスを許可します。データベース・セッション・ベースのアプリケーション・コンテキストでは、この設定は省略され、デフォルトのNULLが使用されます。この設定はオプションです。

    usernameおよびclient_idパラメータは、グローバルにアクセスされるアプリケーション・コンテキストに対して使用されます。詳細は、DBMS_SESSION.SET_CONTEXTのusernameおよびclient_idパラメータを参照してください。

  • client_idは、アプリケーション・コンテキストのアプリケーション固有のclient_id属性(最大64バイト)です。デフォルトはNULLで、クライアントIDが指定されていないことを意味します。データベース・セッション・ベースのアプリケーション・コンテキストでは、この設定は省略され、デフォルトのNULLが使用されます。

関連項目:

10.3.4.8 例: アプリケーション・コンテキストの値を作成する単純なプロシージャ

プロシージャでDBMS_SESSION.SET_CONTEXT文を使用して、アプリケーション・コンテキストの値を設定できます。

例10-1に、empno_ctxアプリケーション・コンテキストの属性を作成する単純なプロシージャの作成方法を示します。

例10-1 アプリケーション・コンテキストの値を作成する単純なプロシージャ

CREATE OR REPLACE PROCEDURE set_empno_ctx_proc(
  emp_value IN VARCHAR2)
 IS   
 BEGIN
  DBMS_SESSION.SET_CONTEXT('empno_ctx', 'empno_attrib', emp_value);
 END; 
/

この例では、次のようになります。

  • emp_value IN VARCHAR2emp_valueを入力パラメータとして使用します。このパラメータは、アプリケーション・コンテキスト属性empno_attribに関連付けられている値を指定します。制限は4000バイトです。

  • DBMS_SESSION.SET_CONTEXT('empno_ctx', 'empno_attrib', emp_value)は、DBMS_SESSION.SET_CONTEXTプロシージャを次のように使用して、アプリケーション・コンテキストの値を設定します。

    • 'empno_ctx'は、アプリケーション・コンテキストのネームスペースを示します。ネームスペース名は一重引用符で囲みます。

    • 'empno_attrib'は、アプリケーション・コンテキストのネームスペースに関連付ける属性を作成します。

    • emp_valueは、empno_attrib属性の値を指定します。ここでは、emp_valueパラメータを参照しています。

これで、set_empno_ctx_procプロシージャを実行して、アプリケーション・コンテキストを設定できます。

EXECUTE set_empno_ctx_proc ('42783');

(実際には、アプリケーション・コンテキストの値はプロシージャ自体に設定することになるため、そのプロシージャがトラステッド・プロシージャとなります。この例は、データが設定される様子を示すことのみを目的に記載しています。)

アプリケーション・コンテキストの設定をチェックするには、次のSELECT文を実行します。

SELECT SYS_CONTEXT ('empno_ctx', 'empno_attrib') empno_attrib FROM DUAL;

EMPNO_ATTRIB
--------------
42783

SESSION_CONTEXTデータ・ディクショナリ・ビューを問い合せると、データベース・インスタンスのカレント・セッションにあるすべてのアプリケーション・コンテキスト設定を検索することもできます。たとえば:

SELECT * FROM SESSION_CONTEXT;

NAMESPACE                ATTRIBUTE          VALUE
--------------------------------------------------
EMPNO_CTX                EMP_ID             42783

10.3.5 データベース・セッションのアプリケーション・コンテキスト・パッケージを実行するログオン・トリガー

データベース・インスタンスにログインした後、ユーザーはデータベース・セッションのアプリケーション・コンテキスト・パッケージを実行する必要があります。

これを自動的に処理するようにログイン・トリガーを作成できます。パッケージを実行するためのEXECUTE権限をユーザーに付与する必要はありません。

次のことに注意してください。

  • ログイン・トリガーによって呼び出されたPL/SQLパッケージ・プロシージャに未処理例外があるか(たとえばセキュリティ・チェックに失敗したために)なんらかの例外を発生すると、ログイン・トリガーは失敗します。ログイン・トリガーに失敗すると、ログインは失敗し、つまりユーザーはデータベースにログインする権限が拒否されます。

  • ログイン・トリガーがパフォーマンスに影響を与える可能性があります。また、ログイン・トリガーは、最初にサンプル・スキーマ・ユーザーでテストしてから、データベース用に作成してください。これによって、エラーがあった場合は簡単に修正できます。

  • 会計帳簿の変更や職階の変更が頻繁にある場合は注意が必要です。この場合、新しい属性値はすぐに選択できない可能性があるため、カーソルの再解析を強制実行して、新しい属性値を選択する必要があります。

ノート:

ユーザー・コンテキスト(EMPNOGROUPMANAGERなどの情報)は、ユーザーがデータにアクセスする前に設定されるため、ログイン・トリガーを使用できます。

10.3.6 例: 単純なログイン・トリガーの作成

CREATE TRIGGER文で簡単なログイン・トリガーを作成できます。

例10-2に、PL/SQLプロシージャを実行する単純なログイン・トリガーを示します。

例10-2 単純なログイン・トリガーの作成

CREATE OR REPLACE TRIGGER set_empno_ctx_trig AFTER LOGON ON DATABASE
 BEGIN
  sec_mgr.set_empno_ctx_proc;
 END;

10.3.7 例: 本番環境用のログイン・トリガーの作成

CREATE TRIGGER文で、本番環境のログイン・トリガーを作成できます。

例10-3は、WHEN OTHERS例外を使用するログイン・トリガーの作成方法を示しています。一方、PL/SQLロジックにエラーが発生して未処理例外を引き起こす場合は、データベースへのすべての接続がブロックされます。

この例は、セキュリティ管理者のスキーマの表にエラーを書き込むWHEN OTHERS例外を示しています。本番環境では、こちらのほうが、出力をユーザー・セッションへ送信することでセキュリティ攻撃を受けやすくなるよりも安全です。

例10-3 本番環境用のログイン・トリガーの作成

CREATE OR REPLACE TRIGGER set_empno_ctx_trig AFTER LOGON ON DATABASE
 BEGIN
  sec_mgr.set_empno_ctx_proc;
 EXCEPTION
  WHEN OTHERS THEN
        v_code := SQLCODE;
        v_errm := SUBSTR(SQLERRM, 1 , 64);
       -- Invoke another procedure,
       -- declared with PRAGMA AUTONOMOUS_TRANSACTION,
       -- to insert information about errors.
  INSERT INTO sec_mgr.errors VALUES (v_code, v_errm, SYSTIMESTAMP);
 END;
/

10.3.8 例: 開発環境用のログイン・トリガーの作成

CREATE TRIGGER文で、開発環境のログイン・トリガーを作成できます。

例10-4に、同じログイン・トリガーを開発環境用に作成する方法を示します。この場合、エラーをデバッグのためにユーザー・セッションに出力できます。

例10-4 開発環境用のログイン・トリガーの作成

CREATE TRIGGER set_empno_ctx_trig 
 AFTER LOGON ON DATABASE
 BEGIN
  sysadmin_ctx.set_empno_ctx_pkg.set_empno;
 EXCEPTION
  WHEN OTHERS THEN
   RAISE_APPLICATION_ERROR(
    -20000, 'Trigger sysadmin_ctx.set_empno_ctx_trig violation. Login denied.');
 END;
/

10.3.9 例: データベース・セッション・ベースのアプリケーション・コンテキストの作成と使用

このチュートリアルでは、データベースへのログインを試みるユーザーのIDをチェックするアプリケーション・コンテキストの作成方法を示します。

10.3.9.1 ステップ1: ユーザー・アカウントの作成とユーザーSCOTTがアクティブであることの確認

このチュートリアルを開始するには、必要なデータベース・アカウントを作成し、SCOTTユーザー・アカウントがアクティブであることを確認する必要があります。

  1. ユーザーSYSとしてログインし、SYSDBA管理権限を使用して接続します。
    sqlplus sys as sysdba
    Enter password: password
    
  2. マルチテナント環境で、適切なPDBに接続します。

    たとえば:

    CONNECT SYS@hrpdb AS SYSDBA
    Enter password: password
    

    使用可能なPDBを検索するには、show pdbsコマンドを実行します。現在のPDBを確認するには、show con_nameコマンドを実行します。

  3. sysadmin_ctxローカル・ユーザー・アカウントを作成します。このアカウントは、データベース・セッション・ベースのアプリケーション・コンテキストを管理します。
    CREATE USER sysadmin_ctx IDENTIFIED BY password;
    GRANT CREATE SESSION, CREATE ANY CONTEXT, CREATE PROCEDURE, CREATE TRIGGER, ADMINISTER DATABASE TRIGGER TO sysadmin_ctx;
    GRANT READ ON HR.EMPLOYEES TO sysadmin_ctx;
    GRANT EXECUTE ON DBMS_SESSION TO sysadmin_ctx;
    

    「パスワードの最低要件」のガイドラインに従って、passwordを安全なパスワードに置き換えます。

  4. Lisa Ozerに対して、次のユーザー・アカウントを作成します。HR.EMPLOYEES表には、lozerというLisa Ozerの電子メール・アカウントがあります。
    GRANT CREATE SESSION TO LOZER IDENTIFIED BY password;
    

    passwordを安全なパスワードに置き換えます。

  5. このチュートリアルでは、サンプル・ユーザーSCOTTも使用するため、DBA_USERSデータ・ディクショナリ・ビューを問い合せて、SCOTTのアカウント・ステータスがOPENになっていることを確認します。
    SELECT USERNAME, ACCOUNT_STATUS FROM DBA_USERS WHERE USERNAME = 'SCOTT';
    

    DBA_USERSビューに、ユーザーSCOTTがロックされて期限切れになっていると表示された場合は、次の文を入力して、SCOTTアカウントのロックを解除し、新しいパスワードを作成します。

    ALTER USER SCOTT ACCOUNT UNLOCK IDENTIFIED BY password;
    

    安全なパスワードを入力します。セキュリティを向上させるため、以前のリリースのOracle Databaseと同じパスワードをSCOTTアカウントに指定しないでください。パスワードを作成するための最低要件は、パスワードの最低要件を参照してください。

10.3.9.2 ステップ2: データベース・セッション・ベースのアプリケーション・コンテキストの作成

sysadmin_ctxユーザーとして、データベース・セッション・ベースのアプリケーション・コンテキストを作成します。

  1. sysadmin_ctxでSQL*Plusにログインします。
    CONNECT sysadmin_ctx -- Or, CONNECT sysadmin_ctx@hrpdb
    Enter password: password
    
  2. 次の文を使用してアプリケーション・コンテキストを作成します。
    CREATE CONTEXT empno_ctx USING set_empno_ctx_pkg;
    

    ユーザーsysadmin_ctxがこのアプリケーション・コンテキストを作成した場合でも、SYSスキーマがこのコンテキストを所有することに注意してください。

10.3.9.3 ステップ3: セッション・データを取得してアプリケーション・コンテキストを設定するパッケージの作成

次に、セッション・データを取得してアプリケーション・コンテキストを設定するPL/SQLパッケージを作成する必要があります。

  • パッケージを作成するには、CREATE OR REPLACE PACKAGE文を使用します。

例10-5に、セッション・データを取得してアプリケーション・コンテキストを設定するために必要なパッケージの作成方法を示します。パッケージを作成する前に、ユーザーsysadmin_ctxでログインしていることを確認してください。(最初の行のCREATE OR REPLACEの前にカーソルを置くことで、このテキストをコピーして貼り付けることができます。)

例10-5 セッション・データを取得してデータベース・セッション・コンテキストを設定するためのパッケージ

CREATE OR REPLACE PACKAGE set_empno_ctx_pkg IS 
   PROCEDURE set_empno; 
 END; 
 /
 CREATE OR REPLACE PACKAGE BODY set_empno_ctx_pkg IS
   PROCEDURE set_empno 
   IS 
    emp_id HR.EMPLOYEES.EMPLOYEE_ID%TYPE;
   BEGIN 
    SELECT EMPLOYEE_ID INTO emp_id FROM HR.EMPLOYEES 
       WHERE email = SYS_CONTEXT('USERENV', 'SESSION_USER');
    DBMS_SESSION.SET_CONTEXT('empno_ctx', 'employee_id', emp_id);
   EXCEPTION  
    WHEN NO_DATA_FOUND THEN NULL;
  END;
 END;
/

このパッケージでは、次の処理を実行するset_empnoというプロシージャが作成されます。

  • emp_id HR.EMPLOYEES.EMPLOYEE_ID%TYPEは、ログインするユーザーの従業員IDを格納する変数emp_idを宣言します。HR.EMPLOYEESEMPLOYEE_ID列と同じデータ型を使用します。

  • SELECT EMPLOYEE_ID INTO emp_id FROM HR.EMPLOYEESは、SELECT文を実行し、HR.EMPLOYEES表のemployee_id列データに格納されている従業員IDをemp_id変数にコピーします。

  • WHERE email = SYS_CONTEXT('USERENV', 'SESSION_USER')は、WHERE句を使用して、セッション・ユーザーの電子メール・アカウントと一致するすべての従業員IDを検索します。SYS_CONTEXT関数は、事前定義のUSERENVコンテキストを使用してユーザー・セッションID (これはemail列データと同じです)を取得します。たとえば、Lisa OzerのユーザーIDと電子メール・アドレスはどちらも同じでlozerです。

  • DBMS_SESSION.SET_CONTEXT('empno_ctx', 'employee_id', emp_id)は、DBMS_SESSION.SET_CONTEXTプロシージャを使用して、アプリケーション・コンテキストを設定します。

    • 'empno_ctx': アプリケーション・コンテキストempno_ctxをコールします。empno_ctxは一重引用符で囲みます。

    • 'employee_id': 属性にemployee_idという名前を指定して、empno_ctxアプリケーション・コンテキストの名前と値のペアの属性値を作成します。employee_idは一重引用符で囲みます。

    • emp_id: employee_id属性の値をemp_id変数に格納された値に設定します。

    要約すると、set_empno_ctx_pkg.set_empnoプロシージャは、「ユーザーのセッションIDを取得して、このユーザーIDをHR.EMPLOYEES表にリストされたユーザーの従業員IDおよび電子メール・アドレスと照合する」プロシージャです。

  • EXCEPTION ... WHEN_NO_DATA_FOUNDは、WHEN NO_DATA_FOUNDシステム例外を追加して、SELECT文によって発生した可能性のあるno data foundエラーを捕捉します。この例外がないと、パッケージとログイン・トリガーは正常に機能し、必要に応じてアプリケーション・コンテキストが設定されますが、HR.EMPLOYEES表にリストされたユーザーを除き、システム管理者以外のユーザーはデータベースにログインできなくなります。他のユーザーは、有効なデータベース・ユーザーであればデータベースにログインできます。アプリケーション・コンテキスト情報が設定された後は、特定のアプリケーションへのユーザー・アクセスを制御する手段として、このセッション情報を使用できます。

10.3.9.4 ステップ4: パッケージに対するログイン・トリガーの作成

ログオン・トリガーは、ユーザーがログインすると実行されます。

  • sysadmin_ctxユーザーとして、set_empno_ctx_pkg.set_empnoパッケージ・プロシージャのログオン・トリガーを作成します。

CREATE TRIGGER set_empno_ctx_trig AFTER LOGON ON DATABASE
 BEGIN
  sysadmin_ctx.set_empno_ctx_pkg.set_empno;
 END;
/
10.3.9.5 ステップ5: アプリケーション・コンテキストのテスト

すべてのコンポーネントの準備ができると、アプリケーション・コンテキストをテストできます。

  1. ユーザーlozerでログインします。
    CONNECT lozer -- Or, CONNECT lozer@hrpdb
    Enter password: password
    

    ユーザーlozerがログインすると、このユーザーの従業員IDがempno_ctxアプリケーション・コンテキストによって収集されます。これは次のようにして確認できます。

    SELECT SYS_CONTEXT('empno_ctx', 'employee_id') emp_id FROM DUAL;
    

    次の出力が表示されます。

    EMP_ID
    --------------------------------------------------------
    168
    
  2. ユーザーSCOTTでログインします。
    CONNECT SCOTT -- Or, CONNECT SCOTT@hrpdb
    Enter password: password
    

    ユーザーSCOTTHR.EMPLOYEES表に従業員としてリストされていないため、empno_ctxアプリケーション・コンテキストではこのユーザーの従業員IDを収集できません。

    SELECT SYS_CONTEXT('empno_ctx', 'employee_id') emp_id FROM DUAL;
    

    次の出力が表示されます。

    EMP_ID
    --------------------------------------------------------
    

これ以降、アプリケーションではユーザー・セッション情報を使用してユーザーがデータベース内で許可されるアクセス数を判別できます。そのためには、Oracle Virtual Private Databaseを使用できます。

10.3.9.6 ステップ6: このチュートリアルのコンポーネントの削除

このチュートリアルのコンポーネントが不要になった場合、それらを削除できます。

  1. SYSDBA管理権限を持つSYSとして接続します。
    CONNECT SYS AS SYSDBA -- Or, CONNECT SYS@hrpdb AS SYSDBA
    Enter password: password
    
  2. ユーザーsysadmin_ctxlozerを削除します。
    DROP USER sysadmin_ctx CASCADE;
    DROP USER lozer;
    
  3. アプリケーション・コンテキストを削除します。
    DROP CONTEXT empno_ctx;
    

    このアプリケーション・コンテキストはsysadmin_ctxが作成しましたが、SYSスキーマの所有となっていることに注意してください。

  4. 他のユーザーがSCOTTを使用しない場合、このアカウントはロックして期限切れにできます。
    ALTER USER SCOTT PASSWORD EXPIRE ACCOUNT LOCK; 

10.3.10 データベース・セッション・ベースのアプリケーション・コンテキストの外部での初期化

データベース・セッション・ベースのアプリケーション・コンテキストを外部で初期化すると、アプリケーション・コンテキストがユーザー・グローバル領域(UGA)に格納されるため、パフォーマンスが向上します。

10.3.10.1 データベース・セッション・ベースのアプリケーション・コンテキストの外部による初期化について

セッション・ベースのアプリケーション・コンテキストを外部で初期化するには、特別な種類のネームスペースを使用する必要があります。

このネームスペースは外部リソースからの属性値の初期化を受け入れ、ローカル・ユーザー・セッションに格納する必要があります。

アプリケーション・コンテキストは外部で初期化することによりUGAに格納されて、属性をセッションから別のセッションへ自動伝播できるようになるため、パフォーマンスが向上します。接続ユーザー・データベース・リンクをサポートするのは、OCIベースの外部ソースから初期化されたアプリケーション・コンテキストのみです。

10.3.10.2 ユーザーからのデフォルト値

Oracle Databaseでは、アプリケーションのユーザーからデフォルト値を取得して使用できます。

ユーザーからデフォルトを取得することが必要な場合があります。最初、これらのデフォルト値はヒントまたはプリファレンスとして機能し、検証後にトラステッド・コンテキストになります。同様に、クライアントでは、一部のデフォルト値を初期化してから、ログイン・イベント・トリガーまたはアプリケーションを使用して値の検証を行うと便利です。

ジョブ・キューに関しては、ジョブ発行ルーチンで、ジョブの発行時に設定されたコンテキストを記録し、バッチ・ジョブの実行時にそのコンテキストをリストアします。コンテキストの整合性を保持するために、ジョブ・キューは、コンテキストを設定する特定のPL/SQLパッケージを回避できません。一方、外部で初期化されたアプリケーション・コンテキストは、コンテキスト値の初期化をジョブ・キュー・プロセスから受け入れます。

リモート・セッションへのコンテキストの自動伝播によって、セキュリティ上の問題が発生する場合があります。開発者または管理者は、ユーザーのログイン時にログイン・トリガーを使用してコンテキストを再設定することで、特定のPL/SQLプロシージャ以外のリソースからデフォルト値を取得するコンテキストを効果的に処理できます。

10.3.10.3 他の外部リソースからの値

アプリケーション・コンテキストによって、外部リソースを介して属性と値の初期化を受け入れることができます。

このような外部リソースには、Oracle Call Interface (OCI)インタフェース、ジョブ・キュー・プロセスまたはデータベース・リンクなどが含まれます。

外部で初期化されたアプリケーション・コンテキストでは、次の機能が提供されます。

  • リモート・セッションの場合は、外部で初期化されたアプリケーション・コンテキスト・ネームスペースにあるコンテキスト値を自動的に伝播します。

  • ジョブ・キューの場合は、外部で初期化されたアプリケーション・コンテキスト・ネームスペースにあるコンテキスト値をリストアします。

  • OCIインタフェースの場合は、外部で初期化されたアプリケーション・コンテキスト・ネームスペースにあるコンテキスト値を初期化するメカニズムを提供します。

Oracle Call Interfaceを使用しているクライアント・プログラムであればこのタイプのネームスペースの初期化は可能ですが、ログイン・イベント・トリガーを使用して値を検証できます。属性の値を解釈して信頼するかどうかはアプリケーションによって異なります。

10.3.10.4 例: 外部化されたデータベース・セッション・ベースのアプリケーション・コンテキストの作成

CREATE CONTEXT SQL文で、外部化されたデータベース・セッション・ベースのアプリケーション・コンテキストを作成できます。

例10-6に、外部ソースから値を取得するデータベース・セッション・ベースのアプリケーション・コンテキストを作成する方法を示します。

例10-6 外部化されたデータベース・セッション・ベースのアプリケーション・コンテキストの作成

CREATE CONTEXT ext_ctx USING ext_ctx_pkg INITIALIZED EXTERNALLY;
10.3.10.5 中間層サーバーからのアプリケーション・コンテキスト値の初期化

中間層サーバーは、データベース・ユーザーのかわりにアプリケーション・コンテキスト値を初期化できます。

このプロセスでは、コンテキスト属性が初期化時にリモート・セッションに対して伝播され、ネームスペースが外部で初期化されている場合、リモート・データベースはこれらの値を受け入れます。

たとえば、OCIまたはJDBC/OCI経由の軽量ユーザー・セッションを作成する3層アプリケーションの場合は、USERENVのPROXY_USER属性にアクセスできます。この属性を使用すると、ユーザー・セッションが中間層アプリケーションによって作成されたかどうかを判断できます。ユーザーがデータへのアクセスを許可されるのは、そのユーザーがプロキシ化されている接続に対してのみです。ユーザーがデータベースに直接接続している場合、そのユーザーはどのデータにもアクセスできません。

Oracle Virtual Private Database内のUSERENVネームスペースからPROXY_USER属性を使用すると、ユーザーによるデータへのアクセスを特定の中間層アプリケーションを経由した場合のみに制限できます。他の方法では、セキュア・アプリケーション・ロールを作成し、ユーザーは特定のプロキシ経由でのみデータベースにアクセスするというポリシーを規定できます。

関連項目:

10.3.11 データベース・セッション・ベースのアプリケーション・コンテキストのグローバルな初期化

データベース・セッション・ベースのアプリケーションが集中格納場所に格納されている場合、そのアプリケーションはLDAPディレクトリ全域から使用できます。

10.3.11.1 データベース・セッション・ベースのアプリケーション・コンテキストのグローバルな初期化について

ユーザーのデータベース・セッション・ベースのアプリケーション・コンテキストは、集中格納場所を使用して格納できます。

集中格納場所を使用することでアプリケーションでは、初期化中にユーザーの識別情報に基づいてユーザー・コンテキストを設定できます。

特に、この機能では、Oracle Label Securityのラベルと権限がサポートされます。アプリケーション・コンテキストをグローバルに初期化すると、多数のユーザーとデータベースのコンテキストを簡単に管理できます。

たとえば、多くの組織では、LDAPベースのディレクトリでユーザー情報を集中管理する必要があります。エンタープライズ・ユーザー・セキュリティは、Oracle Internet Directoryでのユーザーと認可の集中管理をサポートします。ただし、Oracle Virtual Private Databaseの規定に使用するために、アプリケーションではLightweight Directory Access Protocol(LDAP)から追加の属性(ユーザーの職位、組織、物理的な位置など)を取得することが必要な場合があります。これらのタイプの属性は、アプリケーション・コンテキストをグローバルに初期化することで取得できます。

10.3.11.2 LDAPでのデータベース・セッション・ベースのアプリケーション・コンテキストの使用

グローバルに初期化されたアプリケーション・コンテキストは、拡張可能で効率的な標準ディレクトリ・アクセス・プロトコルであるLDAPを使用します。

LDAPディレクトリには、このアプリケーションが割り当てられているユーザーのリストが格納されます。Oracle Databaseでは、ディレクトリ・サービス(通常はOracle Internet Directory)を使用して、エンタープライズ・ユーザーを認証および認可します。

ノート:

Microsoft Active DirectoryやSun MicrosystemsのSunONEなどのサード・パーティ製ディレクトリもディレクトリ・サービスとして使用できます。

orclDBApplicationContext LDAPオブジェクト(groupOfUniqueNamesのサブクラス)は、アプリケーション・コンテキスト値をディレクトリに格納します。アプリケーション・コンテキスト・オブジェクトの場所は、Human Resourcesの例に基づく図10-1で説明しています。

LDAPオブジェクトinetOrgPersonにより、一部の属性では複数のエントリが存在可能です。ただし、これらのエントリがデータベースにロードされ、SYS_LDAP_USER_DEFAULTコンテキスト・ネームスペースでアクセスされると、これらのエントリのうちの最初のエントリのみが返されます。たとえば、ユーザーに対するinetOrgPersonオブジェクトでは、telephoneNumberに複数のエントリが可能です(そのため、ユーザーは複数の電話番号を保存できます)。SYS_LDAP_USER_DEFAULTコンテキスト・ネームスペースを使用すると、最初の電話番号だけが取得されます。提供された属性と値のリストが要求に関して十分でない場合は、DBMS_LDAP PL/SQLパッケージを使用してディレクトリから追加の値をフェッチできます。

LDAP側では、アプリケーション・コンテキスト値のリストをデータベースに返すorclDBApplicationContext値を取得するための内部C関数が必要になります。この例では、HRはネームスペース、TitleProjectは属性、ManagerPromotionは値です。

図10-1 LDAPディレクトリの情報ツリーにおけるアプリケーション・コンテキストの位置

図10-1の説明が続きます
「図10-1 LDAPディレクトリの情報ツリーにおけるアプリケーション・コンテキストの位置」の説明
10.3.11.3 グローバルに初期化されたデータベース・セッション・ベースのアプリケーション・コンテキストの動作

グローバルに初期化されたセキュア・アプリケーションを使用するには、エンタープライズ・ユーザー・セキュリティを最初に構成する必要があります。

次に、データベースとディレクトリのユーザーに対してアプリケーション・コンテキスト値を構成します。

グローバル・ユーザー(エンタープライズ・ユーザー)がデータベースに接続すると、エンタープライズ・ユーザー・セキュリティ機能によって、データベースに接続しているユーザーの識別情報が検証されます。認証後、グローバル・ユーザー・ロールとアプリケーション・コンテキストがディレクトリから取得されます。ユーザーがデータベースにログインするときは、グローバル・ロールと初期アプリケーション・コンテキストがすでに設定されています。

10.3.11.4 データベース・セッション・ベースのアプリケーション・コンテキストのグローバルな初期化

ユーザーの初期アプリケーション・コンテキスト(部門名や職位など)は、LDAPディレクトリに設定および格納できます。

これらの値はユーザーのログイン中に取得されるため、コンテキストは適切に設定されます。さらに、ユーザーに関するすべての情報が取得され、アプリケーション・コンテキスト・ネームスペースSYS_USER_DEFAULTSに格納されます。

  1. データベースにアプリケーション・コンテキストを作成します。
    CREATE CONTEXT hr USING hrapps.hr_manage_pkg INITIALIZED GLOBALLY;
    
  2. 新規のエントリを作成し、LDAPディレクトリに追加します。

    LDAPディレクトリに追加されたエントリの例を次に示します。これらのエントリは、アプリケーション(ネームスペース)HRに属性値Managerを持つ属性名Titleを作成し、ユーザー名user1およびuser2を割り当てます。次の例では、cn=exampleはドメイン名を示します。

    dn: cn=OracleDBAppContext,cn=example,cn=OracleDBSecurity,cn=Products,cn=OracleContext,ou=Americas,o=oracle,c=US
    changetype: add
    cn: OracleDBAppContext
    objectclass: top
    objectclass: orclContainer
    
    dn: cn=hr,cn=OracleDBAppContext,cn=example,cn=OracleDBSecurity,cn=Products,cn=OracleContext,ou=Americas,o=oracle,c=US
    changetype: add
    cn: hr
    objectclass: top
    objectclass: orclContainer
    
    dn: cn=Title,cn=hr, cn=OracleDBAppContext,cn=example,cn=OracleDBSecurity,cn=Products,cn=OracleContext,ou=Americas,o=oracle,c=US
    changetype: add
    cn: Title
    objectclass: top
    objectclass: orclContainer
    
    dn: cn=Manager,cn=Title,cn=hr, cn=OracleDBAppContext,cn=example,cn=OracleDBSecurity,cn=Products,cn=OracleContext,ou=Americas,o=oracle,c=US
    cn: Manager
    objectclass: top
    objectclass: groupofuniquenames
    objectclass: orclDBApplicationContext
    uniquemember: CN=user1,OU=Americas,O=Oracle,L=Redwoodshores,ST=CA,C=US
    uniquemember: CN=user2,OU=Americas,O=Oracle,L=Redwoodshores,ST=CA,C=US

  3. このユーザーに関するLDAP inetOrgPersonオブジェクト・エントリが存在する場合、接続では、複数の属性がinetOrgPersonから取得され、これらがネームスペースSYS_LDAP_USER_DEFAULTに割り当てられます。コンテキストには、inetOrgPersonオブジェクト・クラスの一部であるNULL以外の値のみが移入されます。他の属性は作成されません。

    次に、inetOrgPersonエントリの例を示します。

    dn: cn=user1,ou=Americas,O=oracle,L=redwoodshores,ST=CA,C=US
    changetype: add
    objectClass: top
    objectClass: person
    objectClass: organizationalPerson
    objectClass: inetOrgPerson
    cn: user1
    sn: One
    givenName: User
    initials: UO
    title: manager, product development
    uid: uone
    mail: uone@us.example.com
    telephoneNumber: +1 650 555 0105
    employeeNumber: 00001
    employeeType: full time

  4. データベースに接続します。

    user1がドメインexampleに属するデータベースに接続する場合、user1TitleManagerに設定されます。user1に関するすべての情報が、LDAPディレクトリから取得されます。値は、次の構文を使用して取得できます。

    SYS_CONTEXT('namespace','attribute name') 
    

    たとえば:

    DECLARE 
     tmpstr1 VARCHAR2(30);
     tmpstr2 VARCHAR2(30);
    BEGIN
     tmpstr1 = SYS_CONTEXT('HR','TITLE);
     tmpstr2 = SYS_CONTEXT('SYS_LDAP_USER_DEFAULT','telephoneNumber');
     DBMS_OUTPUT.PUT_LINE('Title is ' || tmpstr1);
     DBMS_OUTPUT.PUT_LINE('Telephone Number is ' || tmpstr2);
    END;
    

    次に、この例の出力を示します。

    Title is Manager
    Telephone Number is +1 650 555 0105

10.3.12 外部化されたデータベース・セッション・ベースのアプリケーション・コンテキスト

多くのアプリケーションでは、ファイングレイン・アクセス・コントロールに使用される属性をデータベース・メタデータ表に格納します。

たとえば、employees表に、コスト・センター、職責、署名認証などのファイングレイン・アクセス・コントロールに有効な情報を含めることができます。ただし、多くの組織ではユーザー情報をOracle Internet DirectoryなどのLDAPベースのディレクトリに集中化して、ユーザーを管理し、アクセス制御しています。アプリケーション・コンテキスト属性は、Oracle Internet Directoryに格納して1人以上のエンタープライズ・ユーザーに割り当てることができます。また、これらの属性は、エンタープライズ・ユーザーがログインすると自動的に取得され、アプリケーション・コンテキストの初期化にも使用されます。

関連項目:

10.4 グローバル・アプリケーション・コンテキスト

グローバル・アプリケーション・コンテキストを使用して、Oracle Real Application Clusters環境などのデータベース・セッション間でアプリケーション値にアクセスできます。

10.4.1 グローバル・アプリケーション・コンテキストについて

グローバル・アプリケーション・コンテキストを使用すると、アプリケーション・コンテキスト値を複数のデータベース・セッション(Oracle RACインスタンスを含む)にわたってアクセス可能にできます。

グローバル・アプリケーション・コンテキスト情報はシステム・グローバル領域(SGA: 共有グローバル領域でSGAと称する場合もあります)に格納されるため、3層アーキテクチャの中間層アプリケーションなど、セッションを使用しないアプリケーションに対して使用できます。

このようなアプリケーションでは、複数のユーザーがアプリケーションに対して認証され、通常は単一の識別情報としてデータベースに接続するため、セッション・ベースのアプリケーション・コンテキストを使用できません。グローバル・アプリケーション・コンテキストは、ユーザー・セッション単位ではなく一度に初期化されます。したがって、接続は接続プールから再利用されるため、パフォーマンスが向上します。

グローバル・アプリケーション・コンテキスト値は、ALTER SYSTEM FLUSH GLOBAL_CONTEXT SQL文を実行してクリアできます。

10.4.2 グローバル・アプリケーション・コンテキストの使用方法

グローバル・アプリケーション・コンテキストには、3種類の一般的な使用方法があります。

使用方法は次のとおりです。

  • 全データベース・ユーザーを対象にしてアプリケーションの値をグローバルに共有する必要がある場合。たとえば、特定の状況に基づいてアプリケーションへのアクセスを禁止することがあります。この場合、アプリケーション・コンテキストが設定する値はユーザーに固有の値ではなく、ユーザーのプライベート・データに基づく値でもありません。アプリケーション・コンテキストは、ある状況を定義して、実行中のアプリケーション・モジュールのバージョンなどを示します。

  • 複数のアプリケーション間を移動する必要があるデータベース・ユーザーがいる場合。この場合、ユーザーの移動先となる第2のアプリケーションには、第1のアプリケーションとは異なるアクセス要件があります。

  • 非データベース・ユーザー(つまり、データベースに認識されていないユーザー)を認証する必要がある場合。データベース・アカウントを持たないこのタイプのユーザーは、通常、Webアプリケーション経由で接続プールを使用して接続します。このようなアプリケーションでは、One Big Application User認証モデルを使用して、複数のユーザーを単一のユーザーとしてデータベースに接続します。このタイプのユーザーを認証するには、そのユーザーのクライアント・セッションIDを使用します。

10.4.3 グローバル・アプリケーション・コンテキストのコンポーネント

グローバル・アプリケーション・コンテキストはパッケージを使用して属性を管理し、中間層アプリケーションを使用してクライアント・セッションIDを管理します。

  • グローバル・アプリケーション・コンテキスト。CREATE CONTEXT SQL文にACCESSED GLOBALLY句を指定して、グローバル・アプリケーション・コンテキストを作成します。この文は、アプリケーション・コンテキスト名を設定し、その名前に、アプリケーション・コンテキスト・データを設定するように設計されたPL/SQLプロシージャを関連付けます。グローバル・アプリケーション・コンテキストは、そのコンテキストを作成したセキュリティ管理者のデータベース・スキーマに作成および格納されます。

  • 属性を設定するPL/SQLパッケージ。このパッケージには、DBMS_SESSION.SET_CONTEXTプロシージャを使用してグローバル・アプリケーション・コンテキストを設定するプロシージャが含まれている必要があります。SET_CONTEXTプロシージャには、この項に記載されている3種類すべての状況に適応するグローバル・アプリケーション・コンテキストを生成できるパラメータが用意されています。このPL/SQLパッケージは、データベース・サーバーで作成、格納および実行します。通常、このパッケージは、それを作成したセキュリティ管理者のスキーマに属します。

  • クライアント・セッションIDを取得および設定する中間層アプリケーション。非データベース・ユーザー(認証にはクライアント・セッションIDが必要)の場合は、中間層アプリケーションでOracle Call Interface(OCI)コールを使用して、それぞれのセッション・データを取得および設定できます。DBMS_SESSION.SET_IDENTIFIERプロシージャを使用してクライアント・セッションIDを設定することもできます。クライアント・セッションIDを作成して非データベース・ユーザー名を保存する利点は、DBA_AUDIT_TRAILDBA_FGA_AUDIT_TRAILDBA_COMMON_AUDIT_TRAILデータ・ディクショナリ・ビューのCLIENT_ID列を問い合せてこのユーザーのアクティビティを監査できることです。

    ノート:

    DBMS_APPLICATION_INFO.SET_CLIENT_INFO設定で値を上書きできることに注意してください。

10.4.4 Oracle Real Application Clusters環境でのグローバル・アプリケーション・コンテキスト

Oracle RAC環境では、グローバル・アプリケーション・コンテキストがロードまたは変更された場合は、常に、既存のアクティブ・インスタンスによってのみ、そのことが認識されます。

Oracle RAC環境でグローバル・アプリケーション・コンテキスト値を設定すると、コンテキスト値をすべてのOracle RACインスタンスに一貫して伝播することによるパフォーマンスのオーバーヘッドが生じることに注意してください。

1つのOracle RACインスタンスでグローバル・アプリケーション・コンテキストをフラッシュすると(ALTER SYSTEM FLUSH GLOBAL_CONTEXT SQL文を使用して)、他のすべてのOracle RACインスタンスでも、すべてのグローバル・アプリケーション・コンテキストがフラッシュされます。

10.4.5 グローバル・アプリケーション・コンテキストの作成

CREATE CONTEXT SQL文によって作成されたグローバル・アプリケーション・コンテキストはSYSスキーマに配置されます。

10.4.5.1 グローバル・アプリケーション・コンテキストの所有権

グローバル・アプリケーション・コンテキストを所有できるのはSYSスキーマのみです。

グローバル・アプリケーション・コンテキストの所有権については、CREATE ANY CONTEXT権限とDROP ANY CONTEXT権限を付与されたユーザーがそのグローバル・アプリケーション・コンテキストを作成および削除できた場合でも、SYSスキーマが所有しています。

Oracle Databaseは、作成したスキーマ・アカウントにコンテキストを関連付けますが、このユーザーを削除した場合、コンテキストはそれでもSYSスキーマの中に存在します。ユーザーSYSであれば、アプリケーション・コンテキストを削除できます。

10.4.5.2 グローバル・アプリケーション・コンテキストの作成

ローカル・アプリケーション・コンテキストと同様、グローバル・アプリケーション・コンテキストもセキュリティ管理者のデータベース・スキーマで作成および格納されます。

グローバル・アプリケーション・コンテキストを作成するには、CREATE ANY CONTEXTシステム権限が必要であり、DROP CONTEXT文でコンテキストを削除するにはDROP ANY CONTEXT権限が必要になります。

  • グローバル・アプリケーション・コンテキストを作成するには、CREATE CONTEXT SQL文を使用してグローバル・アプリケーション・コンテキストを作成し、ACCESSED GLOBALLY句をこのSQL文に含めます。

たとえば:

CREATE OR REPLACE CONTEXT global_hr_ctx USING hr_ctx_pkg ACCESSED GLOBALLY CONTAINER = ALL;

10.4.6 グローバル・アプリケーション・コンテキストを管理するためのPL/SQLパッケージ

DBMS_SESSION PL/SQLパッケージで、グローバル・アプリケーション・コンテキストを管理します。

10.4.6.1 グローバル・アプリケーション・コンテキストを管理するパッケージについて

グローバル・アプリケーション・コンテキストに関連付けるパッケージは、DBMS_SESSIONパッケージを使用してグローバル・アプリケーション・コンテキスト値の設定とクリアを行います。

このプロシージャを使用するには、DBMS_SESSIONパッケージに対するEXECUTE権限が必要です。通常、このパッケージはセキュリティ管理者のデータベース・スキーマに作成および格納されます。DBMS_SESSIONパッケージはSYSスキーマの所有です。

ローカル・アプリケーション・コンテキストの設定に使用するPL/SQLパッケージとは異なり、ユーザー・セッション・データを取得するSYS_CONTEXT関数は挿入しません。グローバル・アプリケーション・コンテキストでは、接続しているすべてのユーザーにとって、セッションの所有者(USERENVコンテキストに記録される)は同じ所有者となるため、この関数を挿入する必要はありません。

プロシージャは、グローバル・アプリケーション・コンテキストのPL/SQLパッケージ内でいつでも実行できます。グローバル・アプリケーション・コンテキストに関連付けられているパッケージ・プロシージャを実行するために、ログイン・トリガーとログオフ・トリガーを作成する必要はありません。一般的に、パッケージ・プロシージャはデータベース・アプリケーション内から実行します。また、非データベース・ユーザーには、中間層アプリケーションを使用してクライアント・セッションIDを取得および設定します。

10.4.6.2 エディションがグローバル・アプリケーション・コンテキストのPL/SQLパッケージの結果に与える影響

グローバル・アプリケーション・コンテキストのパッケージ、Oracle Virtual Private Databaseのパッケージ、およびファイングレイン監査ポリシーは、複数のエディションで使用できます。

次のガイドラインに従ってください。

  • PL/SQLパッケージの結果が、すべてのエディションで同じになるようにします。そのためには、エディションが使用可能になっていないユーザーのスキーマで、パッケージを作成します。エディションが使用可能になっていないユーザーを検索するには、DBA_USERSおよびUSER_USERSデータ・ディクショナリ・ビューを問い合せます。SYSSYSTEM、およびDBA_REGISTRYデータ・ディクショナリ・ビューにリストされている他のデフォルトのOracle Database管理者アカウントは、エディションが使用不可であり、使用可能にすることもできません。

  • PL/SQLパッケージの結果が、パッケージが実行されているエディションの現在の状態に依存するようにします。その結果は、パッケージが適用されるすべてのエディションで異なることがあります。この場合、エディションが使用可能になっているユーザーのスキーマで、パッケージを作成します。スキーマでエディションが使用可能な場合、各エディションに存在するパッケージの実コピーが異なり、各コピーの動作が異なる可能性があります。これは、次のようなシナリオにおいて役立ちます。

    • パッケージで新しいアプリケーション・コンテキストを使用する必要がある場合。

    • パッケージで、別のスキームを使用して入力値をエンコードする必要がある場合。

    • パッケージで、データベースにログインするユーザーに別の検証ルールを適用する必要がある場合。

    グローバル・アプリケーション・コンテキストを設定するPL/SQLパッケージでは、1つのgetter関数を使用して、アプリケーション・コンテキストのキー値のペアを読み取る、プリミティブなSYS_CONTEXTコールをラップします。このgetter関数は、アプリケーション・コンテキストのsetterプロシージャと同じパッケージに配置できます。この方法により、関連する概念を反映するように、アプリケーション・コンテキストのキー値をタグ付けできます。たとえば、setter関数が実際に存在するエディションをタグに使用できます。または、コンテキストを設定するセッションの現行エディションを使用できます、これは、SYS_CONTEXT('USERENV', 'CURRENT_EDITION_NAME')を使用して検索できます。このタグには、setter関数を適用する任意の概念を使用できます。

    関連項目:

    エディションの詳細は、『Oracle Database開発ガイド』を参照してください。

10.4.6.3 DBMS_SESSION.SET_CONTEXTのusernameおよびclient_idパラメータ

DBMS_SESSION.SYS_CONTEXTプロシージャには、グローバル・アプリケーション・コンテキストに使用するclient_idおよびusernameパラメータが用意されています。

これらの設定の組合せによって、作成可能なグローバル・アプリケーション・コンテキストのタイプがどのように制御されるかについて、表10-2で説明します。

表10-2 DBMS_SESSION.SET_CONTEXTのusernameおよびclient_idパラメータの設定

設定の組合せ       結果

usernameNULLに設定

client_idNULLに設定

この組合せでは、すべてのユーザーがアプリケーション・コンテキストにアクセスできます。詳細は、「全データベース・ユーザーを対象としたグローバル・アプリケーション・コンテキスト値の共有」を参照してください。

これらの設定は、データベース・セッション・ベースのアプリケーション・コンテキストにも使用されます。詳細は、「データベース・セッション・ベースのアプリケーション・コンテキストの使用」を参照してください。

usernameをある値に設定

client_idNULLに設定

この組合せでは、username設定が同じであるかぎり、複数のセッションによるアプリケーション・コンテキストへのアクセスが可能です。指定されているユーザー名は有効なデータベース・ユーザーであることが必要です。詳細は、「アプリケーション間を移動するデータベース・ユーザーのグローバル・コンテキスト」を参照してください。

usernameNULLに設定

client_idをある値に設定

この組合せでは、client_idパラメータが同じ値に設定されているかぎり、複数のユーザー・セッションによる1つのアプリケーションへのアクセスが可能です。これによって、全ユーザーのセッションが、アプリケーション・コンテキスト値を参照できます。

usernameをある値に設定

client_idをある値に設定

この組合せでは、次の2つの場合が考えられます。

  • 軽量ユーザー。ユーザーにデータベース・アカウントがない場合は、指定されたユーザー名が接続プール所有者です。client_id設定は、ログインしている非データベース・ユーザーに関連付けられます。

  • データベース・ユーザー。ユーザーがデータベース・ユーザーの場合、この組合せはステートレスWebセッションに使用できます。

SET_CONTEXTプロシージャのusernameパラメータをUSERに設定すると、Oracle Databaseに用意されているUSER関数がコールされます。このUSER関数によって、アプリケーション・コンテキスト取得プロセスからセッション所有者が指定され、アプリケーション・コンテキストを設定したユーザーのみがコンテキストにアクセスできるようになります。USER関数の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

詳細は、「非データベース・ユーザーのグローバル・アプリケーション・コンテキスト」を参照してください。

10.4.6.4 全データベース・ユーザーを対象としたグローバル・アプリケーション・コンテキスト値の共有

全データベース・ユーザーを対象としてグローバル・アプリケーション値を共有して、データベース内のデータへのアクセス権を付与できます。

  • 全データベース・ユーザーを対象としてグローバル・アプリケーションの値を共有するには、SET_CONTEXTプロシージャのnamespaceattributeおよびvalueパラメータを設定します。

10.4.6.5 例: 全データベース・ユーザーを対象としてグローバル・アプリケーション値を管理するためのパッケージ

CREATE PACKAGE文で、全データベース・ユーザーを対象としてグローバル・アプリケーション値を管理できます。

例10-7に、全データベース・ユーザーを対象としてグローバル・アプリケーション・コンテキストを設定およびクリアするパッケージの作成方法を示します。

例10-7 全データベース・ユーザーを対象としてグローバル・アプリケーション値を管理するためのパッケージ

CREATE OR REPLACE PACKAGE hr_ctx_pkg 
   AS  
    PROCEDURE set_hr_ctx(sec_level IN VARCHAR2); 
    PROCEDURE clear_hr_context;
   END;  
  /
  CREATE OR REPLACE PACKAGE BODY hr_ctx_pkg 
   AS                                            
    PROCEDURE set_hr_ctx(sec_level IN VARCHAR2)      
    AS   
    BEGIN  
     DBMS_SESSION.SET_CONTEXT(  
      namespace  => 'global_hr_ctx', 
      attribute  => 'job_role', 
      value      => sec_level);
     END set_hr_ctx;
           
  PROCEDURE clear_hr_context  
    AS
    BEGIN  
     DBMS_SESSION.CLEAR_CONTEXT('global_hr_ctx', 'job_role'); 
    END clear_context;  
  END; 
 /

この例では、次のようになります。

  • DBMS_SESSION.SET_CONTEXT ... END set_hr_ctxは、DBMS_SESSION.SET_CONTEXTプロシージャを使用して、namespaceattributeおよびvalueパラメータの値を設定します。sec_level値は、データベース・アプリケーションがhr_ctx_pkg.set_hr_ctxプロシージャを実行する際に指定されます。

    username値とclient_id値は設定されていません。そのためこれらはNULLです。これによりすべてのユーザー(データベース・ユーザー)が値にアクセスできることになり、サーバー全体として適切な設定になります。

  • namespace => 'global_hr_ctx'は、SET_CONTEXTプロシージャで、namespaceglobal_hr_ctxに設定します。

  • attribute => 'job_role'は、job_role属性を作成します。

  • value => sec_levelは、job_role属性の値をsec_levelに設定します。

  • PROCEDURE clear_hr_contextは、コンテキスト値を消去するclear_hr_contextプロシージャを作成します。詳細は、「セッションをクローズする際のセッション・データのクリア」を参照してください。

通常、このプロシージャは1つのデータベース・アプリケーション内で実行します。たとえば、ログインしているすべてのユーザーが社員であり、「社員」というセキュリティ・レベルを使用する場合は、次の例のようにデータベース・アプリケーション内にコールを埋め込みます。

BEGIN
 hr_ctx_pkg.set_hr_ctx('clerk');
END;
/

プロシージャが正常に完了した場合は、次のようにしてアプリケーション・コンテキスト値をチェックできます。

SELECT SYS_CONTEXT('global_hr_ctx', 'job_role') job_role FROM DUAL;

JOB_ROLE
-----------
clerk

全データベース・ユーザーを対象としてグローバル・アプリケーション・コンテキスト値をクリアするには、次のプロシージャを実行します。

BEGIN
 hr_ctx_pkg.clear_hr_context;
END;
/

グローバル・コンテキスト値が実際にクリアされていることをチェックする場合、次のSELECT文では値は戻りません。

SELECT SYS_CONTEXT('global_hr_ctx', 'job_role') job_role FROM DUAL;

JOB_ROLE
-----------

権限が不十分であることを示すエラー・メッセージがOracle Databaseで返された場合は、グローバル・アプリケーション・コンテキストが正しく作成されていることを確認してください。また、DBA_CONTEXTデータベース・ビューを問い合せて、設定が正しいこと(作成したスキーマからプロシージャがコールされていることなど)を確認してください。

NULLが戻る場合は、誤ってクライアント識別子を設定した可能性があります。クライアント識別子をクリアするには、次のプロシージャを実行します。

EXEC DBMS_SESSION.CLEAR_IDENTIFIER;
10.4.6.6 アプリケーション間を移動するデータベース・ユーザーのグローバル・コンテキスト

アプリケーションによってアクセス要件が異なる場合でも、アプリケーション間を移動するデータベース・ユーザーにグローバル・アプリケーション・コンテキストを使用できます。

これを行うには、DBMS_SESSION.SET_CONTEXTプロシージャにusernameパラメータを含める必要があります。

このパラメータは、すべてのセッションを対象として同じスキーマを使用することを指定します。

次のDBMS_SESSION.SET_CONTEXTパラメータを使用できます。

  • namespace

  • attribute

  • value

  • username

Oracle Databaseは、username値を一致させることで、他のアプリケーションがアプリケーション・コンテキストを認識できるようにします。これによって、ユーザーは複数のアプリケーション間を移動できます。

client_id設定を省略すると、その値はデフォルトのNULLになります。これは、異なるアプリケーションで同じコンテキストを保持するデータベース・ユーザーに対して同じusernameが設定されている場合は、複数のセッションで値を参照できることを意味します。たとえば、各ユーザーを1つのジョブ・ロールに制限し、Oracle Virtual Private Databaseポリシーを使用してユーザー・アクセスを制御するアプリケーション一式を保持できます。

例10-8に、特定のユーザーが複数のアプリケーション間を移動できるように、usernameパラメータを設定する方法を示します。usernameパラメータを使用している部分は、boldで記載しています。

例10-8 複数のアプリケーション間を移動するグローバル・アプリケーション・コンテキスト値のパッケージ

CREATE OR REPLACE PACKAGE hr_ctx_pkg
  AS
    PROCEDURE set_hr_ctx(sec_level IN VARCHAR2, user_name IN VARCHAR2);
    PROCEDURE clear_hr_context;
   END;
  /
  CREATE OR REPLACE PACKAGE BODY hr_ctx_pkg
   AS
    PROCEDURE set_hr_ctx(sec_level IN VARCHAR2, user_name IN VARCHAR2)
    AS
     BEGIN
      DBMS_SESSION.SET_CONTEXT(
       namespace  => 'global_hr_ctx',
       attribute  => 'job_role',
       value      => sec_level,
       username   => user_name);
      END set_hr_ctx;
 
   PROCEDURE clear_hr_context
    AS
     BEGIN
      DBMS_SESSION.CLEAR_CONTEXT('global_hr_ctx');
     END clear_context;
  END;
 / 

通常は、次の例のようにコールを埋め込むことで、このプロシージャをデータベース・アプリケーション内で実行します。user_nameパラメータの値(この場合はscott)には、必ず有効なデータベース・ユーザー名を指定してください。

BEGIN
 hr_ctx_pkg.set_hr_ctx('clerk', 'scott');
END;

このタイプのグローバル・アプリケーション・コンテキストを安全に管理する方法は、自分のアプリケーション範囲内にコードを埋め込み、セキュア・アプリケーション・ロールをユーザーに付与することです。このコードでは、アプリケーション・コンテキストを設定するトラステッドPL/SQLパッケージに対してEXECUTE権限を指定する必要があります。つまり、アプリケーション(ユーザーではなく)がユーザーのコンテキストを設定します。

10.4.6.7 非データベース・ユーザーのグローバル・アプリケーション・コンテキスト

非データベース・ユーザーがクライアント・セッションを開始すると、アプリケーション・サーバーでクライアント・セッションIDが生成されます。

非データベース・ユーザーとはデータベースにとって未知のユーザーのことで、Webアプリケーション・ユーザーなどがこれに当たります。

このIDは、アプリケーション・サーバーで設定後にデータベース・サーバー側へ渡す必要があります。そのためには、DBMS_SESSION.SET_IDENTIFIERプロシージャを使用してクライアント・セッションIDを設定します。

コンテキストを設定するには、サーバー側のPL/SQLプロシージャのDBMS_SESSION.SET_CONTEXTプロシージャにclient_idパラメータを設定します。これでアプリケーション・コンテキストをグローバルに管理できますが、各クライアントには、各自が割り当てられているアプリケーション・コンテキストのみが表示されます。

ここで、client_id値は、グローバル・アプリケーション・コンテキストの正しい属性を取得および設定するためのキーです。クライアント識別子は中間層アプリケーションによって制御され、一度設定されるとクリアされるまでオープン状態のままです。

このタイプのアプリケーション・コンテキストを管理する一般的な方法は、session_id(client_identifier)の値をCookieに格納し、次のリクエストで戻されるように、エンド・ユーザーのHTMLページに送信する方法です。また、アプリケーションの参照表にクライアント識別子を保持し、他のユーザーのために使用されたり、エンド・ユーザーのセッション・タイムアウトを実装するために利用されるのを防止する必要があります。

非データベース・ユーザーの場合は、次のSET_CONTEXTパラメータを構成します。

  • namespace

  • attribute

  • value

  • username

  • client_id

10.4.6.8 例: 非データベース・ユーザーのグローバル・アプリケーション・コンテキスト値を管理するためのパッケージ

CREATE PACKAGE文で、非データベース・ユーザーのグローバル・アプリケーション・コンテキスト値を管理できます。

例10-9に、このタイプのグローバル・アプリケーション・コンテキストを管理するパッケージの作成方法を示します。

例10-9 非データベース・ユーザーのグローバル・アプリケーション・コンテキスト値を管理するためのパッケージ

CREATE OR REPLACE PACKAGE hr_ctx_pkg  
  AS                         
   PROCEDURE set_session_id(session_id_p IN NUMBER); 
   PROCEDURE set_hr_ctx(sec_level_attr IN VARCHAR2,  
      sec_level_val IN VARCHAR2);    
   PROCEDURE clear_hr_session(session_id_p IN NUMBER); 
   PROCEDURE clear_hr_context;  
  END;     
/
  CREATE OR REPLACE PACKAGE BODY hr_ctx_pkg 
   AS                     
    session_id_global NUMBER;  
  PROCEDURE set_session_id(session_id_p IN NUMBER) 
   AS                     
   BEGIN   
    session_id_global := session_id_p; 
    DBMS_SESSION.SET_IDENTIFIER(session_id_p);
  END set_session_id; 
     
  PROCEDURE set_hr_ctx(sec_level_attr IN VARCHAR2,
     sec_level_val IN VARCHAR2) 
   AS     
   BEGIN      
    DBMS_SESSION.SET_CONTEXT(  
     namespace  => 'global_hr_ctx',  
     attribute  => sec_level_attr,
     value      => sec_level_val,
     username   => USER,
     client_id  => session_id_global); 
   END set_hr_ctx;  
        
  PROCEDURE clear_hr_session(session_id_p IN NUMBER)
   AS 
   BEGIN   
      DBMS_SESSION.SET_IDENTIFIER(session_id_p); 
      DBMS_SESSION.CLEAR_IDENTIFIER;  
   END clear_hr_session;   
   
  PROCEDURE clear_hr_context 
  AS       
  BEGIN            
   DBMS_SESSION.CLEAR_CONTEXT('global_hr_ctx', session_id_global);
  END clear_hr_context;  
 END;  
 /

この例では、次のようになります。

  • session_id_global NUMBERは、クライアント・セッションIDを格納するsession_id_global変数を作成します。このsession_id_global変数は、グローバル・アプリケーション・コンテキストの属性を作成して値を割り当てるプロシージャも含めて、パッケージ定義全体から参照されます。これは、グローバル・アプリケーション・コンテキストの値が、この特定のセッションIDと常に関連付けられることを意味します。

  • PROCEDURE set_session_id ... END set_session_idは、set_session_idプロシージャを作成します。これは、クライアント・セッションIDをsession_id_global変数に書き込むプロシージャです。

  • PROCEDURE set_hr_ctx ... END set_hr_ctxは、set_hr_ctxプロシージャを作成します。このプロシージャによりグローバル・アプリケーション・コンテキスト属性が作成されて、これらの属性に値を割り当てることができるようになります。このプロシージャ内では、次のようになります。

    • username => USERは、username値を指定します。この例では、Oracle Databaseによって指定される、コンテキスト取得プロセスからセッション所有者を追加するためのUSER関数を呼び出すことによって設定します。USER関数によって、アプリケーション・コンテキストを設定するユーザーのみがコンテキストにアクセスできるようになります。USER関数の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

      NULL(usernameパラメータのデフォルト)を指定すると、すべてのユーザーがコンテキストにアクセスできるようになります。

      username値とclient_id値の両方を設定した場合は、2つの異なる使用目的が考えられます。軽量ユーザーの場合は、usernameパラメータに対して接続プール所有者(APPS_USERなど)を設定し、client_idに対してクライアント・セッションIDを設定します。ステートレスWebセッションを使用する場合は、ログインしたユーザーと同じデータベース・ユーザーをuser_nameパラメータに設定し、このユーザーが同じクライアント・セッションIDを保持していることを確認します。異なるusernameclient_idを設定した場合の動作の例は、「DBMS_SESSION.SET_CONTEXTのusernameおよびclient_idパラメータ」を参照してください。

    • client_id => session_id_globalは、client_id値を指定します。この例では、この値をsession_id_global変数に設定しています。これによって、ここで定義したコンテキスト設定が特定のクライアント・セッションID(つまり、set_session_idプロシージャを実行する際に設定されるID)に関連付けられます。client_idパラメータにデフォルトのNULLを指定すると、すべてのセッションでグローバル・アプリケーション・コンテキストの設定を使用できるようになります。

  • PROCEDURE clear_hr_session ... END clear_hr_sessionは、クライアント・セッション識別子を消去するclear_hr_sessionプロシージャを作成します。AS句は、正しいセッションID、つまりCREATE OR REPLACE PACKAGE BODY hr_ctx_pkgプロシージャで定義されている変数session_id_pに格納されているIDをクリアするように設定します。

  • PROCEDURE clear_hr_context ... END clear_hr_contextは、clear_hr_contextプロシージャを作成します。このプロシージャは、global_hr_ctx変数によって定義された現行のユーザー・セッションのコンテキスト設定を消去します。詳細は、「セッションをクローズする際のセッション・データのクリア」を参照してください。

10.4.6.9 セッションをクローズする際のセッション・データのクリア

アプリケーション・コンテキストはメモリー内に存在するので、ユーザーがセッションを終了したときは、client_identifierコンテキスト値をクリアする必要があります。

この消去によってメモリーが解放され、残存している値を他のユーザーが誤って使用することがなくなります。
  • ユーザーのセッション終了時にセッション・データをクリアするには、サーバー側のPL/SQLパッケージで、次のいずれかの方法を使用します。

    • ユーザーがセッションを終了したときにクライアント識別子をクリアする方法。DBMS_SESSION.CLEAR_IDENTIFIERプロシージャを使用します。たとえば:

      DBMS_SESSION.CLEAR_IDENTIFIER;
      
    • コンテキストをクリアしてもセッションを続行する方法。セッションを続行しながらコンテキストを消去する必要がある場合は、DBMS_SESSION.CLEAR_CONTEXTまたはDBMS_SESSION.CLEAR_ALL_CONTEXTプロシージャを使用します。たとえば:

      DBMS_SESSION.CLEAR_CONTEXT('my_ctx', 'my_attribute');
      

      CLEAR_CONTEXTプロシージャは現行ユーザーのコンテキストを消去します。たとえば、アプリケーション・サーバーを停止する必要がある場合など、すべてのユーザーのコンテキスト値を消去するには、CLEAR_ALL_CONTEXTプロシージャを使用します。

      グローバル・アプリケーション・コンテキスト値は消去されるまで使用可能です。したがって、他のセッションがこれらの値にアクセスしないように、CLEAR_CONTEXTまたはCLEAR_ALL_CONTEXTを使用してください。コンテキストの値が変更された場合、その内容はただちに反映され、SYS_CONTEXTファンクションによって値を取得する後続のコールでは、最新の値が戻されます。

10.4.7 クライアント・セッションIDを管理するための中間層アプリケーションへのコールの埋込み

中間層アプリケーションにコールを埋め込み、クライアント・セッションIDを管理できます。

10.4.7.1 中間層アプリケーションを使用したクライアント・セッションIDの管理について

アプリケーション・サーバーはクライアント・セッションIDを生成します。

中間層アプリケーションから、クライアント・セッションIDを取得、設定、およびクリアできます。そのために、Oracle Call Interface (OCI)コールとDBMS_SESSION PL/SQLパッケージ・プロシージャのどちらかを中間層アプリケーション・コードに埋め込むことができます。

アプリケーションによってユーザーが認証され、クライアント識別子が設定されてカレント・セッションに設定されます。PL/SQLパッケージSET_CONTEXTによって、アプリケーション・コンテキストにclient_identifier値が設定されます。

10.4.7.2 ステップ1: 中間層アプリケーションを使用したクライアント・セッションIDの取得

ユーザーがクライアント・セッションを開始すると、アプリケーション・サーバーでクライアント・セッションIDが生成されます。

このIDは、ユーザーのアクセス認証時に使用する目的で取得できます。

  • このクライアントIDを取得するには、次のいずれかの文でOCIStmtExecuteコールを使用します。

    • SELECT SYS_CONTEXT('userenv', 'client_identifier') FROM DUAL;

    • SELECT CLIENT_IDENTIFIER from V$SESSION;

    • SELECT value FROM session_context WHERE attribute='CLIENT_IDENTIFIER';

たとえば、OCIStmtExecuteコールを使用してクライアント・セッションID値を取得するには:

oratext    clientid[31];  
 OCIDefine  *defnp1 = (OCIDefine *) 0;
 OCIStmt    *statementhndle;
 oratext    *selcid = (oratext *)"SELECT SYS_CONTEXT('userenv',
            'client_identifier') FROM  DUAL";  

OCIStmtPrepare(statementhndle, errhp, selcid,
  (ub4) strlen((char *) selcid), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);

OCIDefineByPos(statementhndle, &defnp1, errhp, 1, (dvoid *)clientid, 31,
  SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, OCI_DEFAULT);

OCIStmtExecute(servhndle, statementhndle, errhp, (ub4) 1, (ub4) 0,
 (CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT);

  printf("CLIENT_IDENTIFIER = %s \n", clientid);

この例では、次のようになります。

  • oratextOCIDefineOCIStmtおよびoratextは、クライアント・セッションID、OCIDefineの参照コール、文ハンドルおよび使用するSELECT文を格納するための変数を作成します。

  • OCIStmtPrepareは、文selcidを実行する準備を整えます。

  • OCIDefineByPosは、クライアント・セッションIDの出力変数clientidを定義します。

  • OCIStmtExecuteは、selcid変数に格納されている文を実行します。

  • printfは、取得したクライアント・セッションIDに書式を設定した出力を表示します。

10.4.7.3 ステップ2: 中間層アプリケーションを使用したクライアント・セッションIDの設定

次に、中間層アプリケーションを使用してクライアント・セッションIDを設定します。

10.4.7.3.1 中間層アプリケーションを使用したクライアント・セッションIDの設定について

OCIStmtExecuteコールを使用してクライアント・セッションIDを取得した後は、このIDを設定できます。

サーバー側のPL/SQLパッケージのDBMS_SESSION.SET_CONTEXTプロシージャによってこのセッションIDを設定した後、必要に応じてアプリケーション・コンテキスト値を上書きします。

中間層アプリケーション・コードにより、クライアント・セッションID値(前の例でuser_idに書き込まれた値など)がサーバー側のDBMS_SESSION.SET_CONTEXTプロシージャで定義されているclient_id設定と一致することを確認する必要があります。アプリケーション・サーバー側では、次の順序でコールする必要があります。

  1. 現行のクライアント・セッションIDを取得します。セッションにはこのIDがすでに設定されていますが、本当に正しい値かどうかを確認するほうが安全です。

  2. 現行のクライアント・セッションIDをクリアします。消去することで、異なるエンド・ユーザーからのリクエストにサービスを提供するようにアプリケーションを準備します。

  3. 新規クライアント・セッションIDまたはエンド・ユーザーに割当て済のクライアント・セッションIDを設定します。この設定によって、セッションは異なるグローバル・アプリケーション・コンテキストの値セットを使用するようになります。

10.4.7.3.2 中間層アプリケーションを使用したクライアント・セッションIDの設定

Oracle Call InterfaceまたはDBMS_SESSION PL/SQLパッケージによって、中間層アプリケーションを使用してクライアント・セッションIDを設定できます。

  • 次のいずれかの方法を使用して、アプリケーション・サーバー側にクライアント・セッションIDを設定します。

    • Oracle Call Interface。OCIAttrSet OCIコールにOCI_ATTR_CLIENT_IDENTIFIER属性を設定します。この属性は、エンド・ユーザーの識別情報を追跡するためのクライアント識別子をセッション・ハンドルに設定します。

      次の例は、OCIAttrSetATTR_CLIENT_IDENTIFIERパラメータを使用する方法を示しています。user_id設定は、ログインしているユーザーのIDが格納されている変数を参照します。

      OCIAttrSet((void *)session_handle, (ub4) OCI_HTYPE_SESSION, 
                 (void *) user_id, (ub4)strlen(user_id),
                 OCI_ATTR_CLIENT_IDENTIFIER, error_handle);
      
    • DBMS_SESSIONパッケージ。DBMS_SESSION.SET_IDENTIFIERプロシージャを使用して、グローバル・アプリケーション・コンテキストのクライアント識別子を設定します。たとえば、ログインしているユーザーのIDをuser_idという変数に格納している場合は、中間層アプリケーションのコードに次の行を入力することになります。

      DBMS_SESSION.SET_IDENTIFIER(user_id);

ノート:

アプリケーションでCLIENT_IDENTIFIERとして使用するセッションIDを生成する場合、そのセッションIDは適度にランダムで、ネットワーク上では暗号化によって保護されている必要があります。セッションIDがランダムでない場合は、不正なユーザーがセッションIDを推測し、他のユーザーのデータにアクセスする可能性があります。セッションIDがネットワーク上で暗号化されていない場合は、不正なユーザーがセッションIDを取得して、接続にアクセスする可能性があります。

ネットワーク・データの暗号化を使用して、セッションIDを暗号化できます。詳細は、Oracle Databaseのネイティブ・ネットワーク暗号化とデータ整合性の構成を参照してください。

10.4.7.3.3 クライアント識別子の値のチェック

OCIAttrSetおよびDBMS_SESSION.SET_IDENTIFIERでは、クライアント識別子の値をチェックできます。

  • クライアント識別子の値をチェックするには、次のいずれかの方法を使用します。

    • SYS_CONTEXT関数を使用してチェックするには:

      SELECT SYS_CONTEXT('userenv', 'client_identifier') FROM DUAL;
      
    • V$SESSIONビューを問い合せてチェックするには:

      SELECT CLIENT_IDENTIFIER from V$SESSION;
10.4.7.4 ステップ3: 中間層アプリケーションを使用したセッション・データのクリア

アプリケーション・コンテキストは、すべてがメモリー内に存在します。

ユーザーがセッションを終了したときは、client_identifier値のコンテキストをクリアする必要があります。この消去によってメモリーが解放され、残存している値を他のユーザーが誤って使用することがなくなります。

  • ユーザーのセッション終了時にセッション・データをクリアするには、中間層アプリケーションのコードで、次のいずれかの方法を使用します。

    • ユーザーがセッションを終了したときにクライアント識別子をクリアする方法。DBMS_SESSION.CLEAR_IDENTIFIERプロシージャを使用します。たとえば:

      DBMS_SESSION.CLEAR_IDENTIFIER;
      
    • コンテキストをクリアしてもセッションを続行する方法。セッションを続行しながらコンテキストを消去する必要がある場合は、DBMS_SESSION.CLEAR_CONTEXTまたはDBMS_SESSION.CLEAR_ALL_CONTEXTプロシージャを使用します。たとえば:

      DBMS_SESSION.CLEAR_CONTEXT(namespace, client_identifier, attribute);
      

      CLEAR_CONTEXTプロシージャは現行ユーザーのコンテキストを消去します。たとえば、アプリケーション・サーバーを停止する必要がある場合など、すべてのユーザーのコンテキスト値を消去するには、CLEAR_ALL_CONTEXTプロシージャを使用します。

      グローバル・アプリケーション・コンテキスト値は消去されるまで使用可能です。したがって、他のセッションがこれらの値にアクセスしないように、CLEAR_CONTEXTまたはCLEAR_ALL_CONTEXTを使用してください。

10.4.8 例: クライアント・セッションIDを使用するグローバル・アプリケーション・コンテキストの作成

このチュートリアルでは、クライアント・セッションIDを使用するグローバル・アプリケーション・コンテキストの作成を示しています。

10.4.8.1 このチュートリアルについて

この例は、軽量ユーザーのアプリケーション用にクライアント・セッションIDを使用するグローバル・アプリケーション・コンテキストを作成する方法を示しています。

非データベース・ユーザーの接続プールを使用したアクセスを制御する方法を示しています。マルチテナント環境を使用している場合、このチュートリアルは現在のPDBのみに適用されます。

10.4.8.2 ステップ1: ユーザー・アカウントの作成

セキュリティ管理者はアプリケーション・コンテキストおよびそのパッケージを管理し、ユーザー・アカウントは接続プールを所有します。

  1. SYSDBA管理権限を持つSYSとしてSQL*Plusにログインします。
    sqlplus sys as sysdba
    Enter password: password
    
  2. マルチテナント環境で、適切なPDBに接続します。

    たとえば:

    CONNECT SYS@my_pdb AS SYSDBA
    Enter password: password
    

    利用可能なPDBを検索するには、DBA_PDBSデータ・ディクショナリ・ビューを問い合せます。現在のPDBを確認するには、show con_nameコマンドを実行します。

  3. sysadmin_ctxローカル・ユーザー・アカウントを作成します。このアカウントは、グローバル・アプリケーション・コンテキストを管理します。
    CREATE USER sysadmin_ctx IDENTIFIED BY password CONTAINER = CURRENT;
    GRANT CREATE SESSION, CREATE ANY CONTEXT, CREATE PROCEDURE TO sysadmin_ctx;
    
    GRANT EXECUTE ON DBMS_SESSION TO sysadmin_ctx;
    

    「パスワードの最低要件」のガイドラインに従って、passwordを安全なパスワードに置き換えます。

  4. 接続プールの所有者にするローカル・データベース・アカウントapps_userを作成します。
    CREATE USER apps_user IDENTIFIED BY password CONTAINER = CURRENT;
    GRANT CREATE SESSION TO apps_user;
    

    passwordを安全なパスワードに置き換えます。

10.4.8.3 ステップ2: グローバル・アプリケーション・コンテキストの作成

次に、グローバル・アプリケーション・コンテキストを作成します。

  1. セキュリティ管理者sysadmin_ctxでログインします。
    CONNECT sysadmin_ctx -- Or, CONNECT sysadmin_ctx@hrpdb
    Enter password: password
    
  2. cust_ctxグローバル・アプリケーション・コンテキストを作成します。
    CREATE CONTEXT global_cust_ctx USING cust_ctx_pkg ACCESSED GLOBALLY;
    

    cust_ctxコンテキストが作成され、セキュリティ管理者sysadmin_ctxのスキーマに関連付けられます。ただし、アプリケーション・コンテキストはSYSスキーマが所有します。

10.4.8.4 ステップ3: グローバル・アプリケーション・コンテキストのパッケージの作成

PL/SQLパッケージは、作成したグローバル・アプリケーション・コンテキストを管理します。

  1. sysadmin_ctxとして、次のPL/SQLパッケージを作成します。
    CREATE OR REPLACE PACKAGE cust_ctx_pkg
      AS
       PROCEDURE set_session_id(session_id_p IN NUMBER); 
       PROCEDURE set_cust_ctx(sec_level_attr IN VARCHAR2, 
         sec_level_val IN VARCHAR2);
       PROCEDURE clear_hr_session(session_id_p IN NUMBER);
       PROCEDURE clear_hr_context;
      END;
     /
    CREATE OR REPLACE PACKAGE BODY cust_ctx_pkg
      AS
      session_id_global NUMBER;
     
     PROCEDURE set_session_id(session_id_p IN NUMBER) 
      AS
      BEGIN
       session_id_global := session_id_p;
       DBMS_SESSION.SET_IDENTIFIER(session_id_p);
     END set_session_id;
     
     PROCEDURE set_cust_ctx(sec_level_attr IN VARCHAR2, sec_level_val IN VARCHAR2)
      AS
      BEGIN
       DBMS_SESSION.SET_CONTEXT(
        namespace  => 'global_cust_ctx',
        attribute  => sec_level_attr,
        value      => sec_level_val,
        username   => USER, -- Retrieves the session user, in this case, apps_user
        client_id  => session_id_global);
      END set_cust_ctx;
     
      PROCEDURE clear_hr_session(session_id_p IN NUMBER)
       AS
       BEGIN
         DBMS_SESSION.SET_IDENTIFIER(session_id_p);
         DBMS_SESSION.CLEAR_IDENTIFIER;
       END clear_hr_session;
    
     PROCEDURE clear_hr_context
      AS
      BEGIN
       DBMS_SESSION.CLEAR_CONTEXT('global_cust_ctx', session_id_global);
      END clear_hr_context;
     END;
    /
    

    このタイプのパッケージの動作に関する詳細説明は、例10-9を参照してください。

  2. cust_ctx_pkgパッケージに対するEXECUTE権限を接続プール所有者apps_userに付与します。
    GRANT EXECUTE ON cust_ctx_pkg TO apps_user;
10.4.8.5 ステップ4: 新規作成したグローバル・アプリケーション・コンテキストのテスト

この時点で、このグローバル・アプリケーション・コンテキストとセッションIDの設定について動作を確認します。

  1. 接続プール所有者(ユーザーapps_user)でSQL*Plusにログインします。

    CONNECT apps_user -- Or, CONNECT apps_user@hrpdb
    Enter password: password
    
  2. 接続プール・ユーザーのログイン時に、アプリケーションでは、次のようにクライアント・セッション識別子が設定されます。

    BEGIN
     sysadmin_ctx.cust_ctx_pkg.set_session_id(34256);
    END;
    /
    
  3. クライアント・セッション識別子の値をテストします。

    1. セッションIDを設定します。

      EXEC sysadmin_ctx.cust_ctx_pkg.set_session_id(34256);
      
    2. セッションIDをチェックします。

      SELECT SYS_CONTEXT('userenv', 'client_identifier') FROM DUAL;
      

      次の出力が表示されます。

      SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER')
      --------------------------------------------------
      34256
      
  4. グローバル・アプリケーション・コンテキストを次のように設定します。

    EXEC sysadmin_ctx.cust_ctx_pkg.set_cust_ctx('Category', 'Gold Partner');
    EXEC sysadmin_ctx.cust_ctx_pkg.set_cust_ctx('Benefit Level', 'Highest');
    

    (実際には、ステップ2でクライアント・セッション識別子を設定した方法と同様に、中間層アプリケーションでグローバル・アプリケーション・コンテキスト値を設定することになります。)

  5. 次のSELECT SYS_CONTEXT文を入力し、設定が正しいことをチェックします。

    col category format a13
    col benefit_level format a14
    
    SELECT SYS_CONTEXT('global_cust_ctx', 'Category') category, SYS_CONTEXT('global_cust_ctx', 'Benefit Level') benefit_level FROM DUAL;
    

    次の出力が表示されます。

    CATEGORY       BENEFIT_LEVEL
    -------------  --------------
    Gold Partner   Highest
    

apps_userがここで(クライアント・セッション34256内で)実行したのは、非データベース・ユーザーにかわってグローバル・アプリケーション・コンテキストを設定したことです。このコンテキストは、DBMS_SESSION.SET_CONTEXTCategoryおよびBenefit Level属性をそれぞれGold PartnerおよびHighestに設定します。このコンテキストは、クライアントID 34256のユーザーapps_userに対してのみ存在します。非データベース・ユーザーがバックグラウンドでログインした場合、そのユーザーは、実際には接続プール・ユーザーapps_userでログインしたことになります。このようにして、非データベース・ユーザーは、Gold PartnerおよびHighestのコンテキスト値を使用できます。

データベース・ユーザーであるユーザーが、相応のアプリケーションを使用せずにログインすると仮定します。(たとえば、SQL*Plusを使用してログインします。)このユーザーは接続プール・ユーザー(apps_user)でログインしていないため、グローバル・アプリケーション・コンテキストは、該当しないユーザーに対して空で表示されます。これは、このコンテキストがapps_userセッションで作成および設定されていたためです。ユーザーがSELECT SYS_CONTEXT文を実行すると、次の出力が表示されます。

CATEGORY       BENEFIT_LEVEL
-------------  --------------
10.4.8.6 ステップ5: セッションIDの変更とグローバル・アプリケーション・コンテキストの再テスト

次に、セッションIDをクリアして変更し、グローバル・アプリケーション・コンテキストを再テストします。

  1. ユーザーapps_userとして、セッションIDをクリアします。
    EXEC sysadmin_ctx.cust_ctx_pkg.clear_hr_session(34256);
    
  2. グローバル・アプリケーション・コンテキストを再度チェックしてください。
    SELECT SYS_CONTEXT('global_cust_ctx', 'Category') category, SYS_CONTEXT('global_cust_ctx', 'Benefit Level') benefit_level FROM DUAL;
    
    CATEGORY       BENEFIT_LEVEL
    -------------  --------------
    

    apps_userによってセッションIDがクリアされたため、グローバル・アプリケーション・コンテキストの設定は使用できません。

  3. セッションIDに34256をリストアしてから、コンテキスト値をチェックします。
    EXEC sysadmin_ctx.cust_ctx_pkg.set_session_id(34256);
    
    SELECT SYS_CONTEXT('global_cust_ctx', 'Category') category, SYS_CONTEXT('global_cust_ctx', 'Benefit Level') benefit_level FROM DUAL;
    

    次の出力が表示されます。

    CATEGORY       BENEFIT_LEVEL
    -------------  --------------
    Gold Partner   Highest
    

    このように、セッションIDを34256に再設定すると、アプリケーション・コンテキスト値が元に戻ります。要約すると、グローバル・アプリケーション・コンテキストはこのユーザーに対して1度のみ設定しますが、クライアント・セッションIDはユーザーがログインするたびに設定する必要があります。

  4. ここで、グローバル・アプリケーション・コンテキストの値をクリアした後、その値をチェックしてください。
    EXEC sysadmin_ctx.cust_ctx_pkg.clear_hr_context;
    
    SELECT SYS_CONTEXT('global_cust_ctx', 'Category') category, SYS_CONTEXT('global_cust_ctx', 'Benefit Level') benefit_level FROM DUAL;
    

    次の出力が表示されます。

    CATEGORY       BENEFIT_LEVEL
    -------------  --------------
    

    この時点では、クライアント・セッションIDの34256は適切に設定されていますが、アプリケーション・コンテキストの設定はすでに存在していません。これで、以前に設定したアプリケーション・コンテキストの値を使用せずに、このユーザーのセッションを続行できます。

10.4.8.7 ステップ6: このチュートリアルのコンポーネントの削除

このチュートリアルのコンポーネントが不要になった場合、それらを削除できます。

  1. SYSDBA管理権限を持つSYSとして接続します。
    CONNECT SYS AS SYSDBA -- Or, CONNECT SYS@mypdb AS SYSDBA
    Enter password: password
    
  2. グローバル・アプリケーション・コンテキストを削除します。
    DROP CONTEXT global_cust_ctx;
    

    このグローバル・アプリケーション・コンテキストはsysadmin_ctxが作成しましたが、SYSスキーマの所有となっていることに注意してください。

  3. 2人のサンプル・ユーザーを削除します。
    DROP USER sysadmin_ctx CASCADE;
    DROP USER apps_user;

10.4.9 グローバル・アプリケーション・コンテキスト・プロセス

簡単なグローバル・アプリケーション・コンテキストはデータベース・ユーザー・アカウントを使用し、ユーザー・セッションを作成します。グローバル・アプリケーション・コンテキストは軽量ユーザー用です。

10.4.9.1 単純なグローバル・アプリケーション・コンテキスト・プロセス

簡単なグローバル・アプリケーション・コンテキストのプロセスでは、アプリケーションは、データベース・ユーザーを使用してユーザー・セッションを作成します。

単純なグローバル・アプリケーション・コンテキスト・プロセスのコンテキスト属性の値は、SELECT文から取得できます。

クライアント識別子12345をクライアントSCOTTに割り当てたアプリケーション・サーバーAppSvrを想定します。AppSvrアプリケーションは、SCOTTユーザーを使用してセッションを作成します。(つまり、接続プールではありません。)コンテキスト属性に割り当てる値には、ユーザーの職責コードが入っている表でSELECT文を実行して取得された値など、あらゆる値を使用できます。アプリケーション・コンテキストは移入されると、メモリーに保存されます。そのため、職責コードを必要とするアクションはSYS_CONTEXTコールによってすぐに職責コードにアクセスできるようになり、表にアクセスするオーバーヘッドもありません。このケースのローカル・コンテキストに対するグローバル・コンテキストの唯一の利点は、SCOTTがアプリケーションを頻繁に変更して、各アプリケーションで同じコンテキストを使用したような場合です。

次のステップは、グローバル・アプリケーション・コンテキスト・プロセスでSCOTTのクライアント識別子を設定する方法を示しています。

  1. 管理者は次の文を使用して、グローバル・コンテキスト・ネームスペースを作成します。

    CREATE OR REPLACE CONTEXT hr_ctx USING hr.init ACCESSED GLOBALLY;
    
  2. 管理者は、hr_ctxアプリケーション・コンテキスト用にPL/SQLパッケージを作成し、このクライアント識別子には、HRネームスペースに値13があるresponsibilityと呼ばれるアプリケーション・コンテキストがあることを示します。

    CREATE OR REPLACE PROCEDURE hr.init 
     AS
     BEGIN
      DBMS_SESSION.SET_CONTEXT(
        namespace => 'hr_ctx', 
        attribute => 'responsibility', 
        value     => '13', 
        username  => 'SCOTT', 
        client_id => '12345' );
     END;
    /
    

    このPL/SQLプロシージャはHRデータベース・スキーマに格納されていますが、通常は、セキュリティ管理者のスキーマに格納されます。

  3. scottAppSvrを使用してデータベースに接続するたびに、AppSvrアプリケーションによって、次のコマンドが発行され、接続クライアントの識別情報が指定されます。

    EXEC DBMS_SESSION.SET_IDENTIFIER('12345');
    
  4. データベース・セッション内にSYS_CONTEXT('hr_ctx','responsibility')コールがある場合、データベースによって、クライアント識別子12345がグローバル・コンテキストと照合され、値13が戻されます。

  5. このデータベース・セッションの終了時には、AppSvrによって、次のプロシージャが発行され、クライアント識別子がクリアされます。

    EXEC DBMS_SESSION.CLEAR_IDENTIFIER( );
    
  6. アプリケーション・コンテキストによって使用されたメモリーを解放するために、AppSvrは次のプロシージャを発行します。

    DBMS_SESSION.CLEAR_CONTEXT('hr_ctx', '12345');
    

    CLEAR_CONTEXTが必要なのは、ユーザー・セッションが、明示的なログアウト、タイムアウトまたはAppSvrアプリケーションで判断される他の状況でアクティブでない場合です。

ノート:

セッションのクライアント識別子は、クリアされるとNULL値になります。したがって、後続のSYS_CONTEXTコールでは、SET_IDENTIFIERインタフェースを使用してクライアント識別子を再設定しないかぎり、クライアント識別子がNULLのアプリケーション・コンテキストのみが取得されます。

10.4.9.2 軽量ユーザー用のグローバル・アプリケーション・コンテキスト・プロセス

軽量ユーザーにグローバル・アプリケーション・コンテキストを設定できます。

このアクセスは、他のユーザーがログイン時にグローバル・アプリケーション・コンテキストにアクセスできないように構成できます。

次のステップは、軽量ユーザー・アプリケーション用のグローバル・アプリケーション・コンテキスト・プロセスを示しています。軽量ユーザーrobertは、アプリケーションを介してデータベースに認識されていません。

  1. 管理者は次の文を使用して、グローバル・コンテキスト・ネームスペースを作成します。

    CREATE CONTEXT hr_ctx USING hr.init ACCESSED GLOBALLY;
    
  2. HRアプリケーション・サーバーAppSvrが起動し、ユーザーappsmgrとしてHRデータベースへの複数の接続を確立します。

  3. ユーザーrobertHRアプリケーション・サーバーにログインします。

  4. AppSvrがアプリケーションに対してrobertを認証します。

  5. AppSvrがこの接続に対して一時的なセッションID12345を割り当てます(またはアプリケーション・ユーザーIDを使用します)。

  6. セッションIDが、robertが使用するWebブラウザにCookieの一部として戻されるか、またはAppSvrによって保持されます。

  7. AppSvrhr.initパッケージをコールして、このクライアントのアプリケーション・コンテキストを初期化すると、次の文が発行されます。

    DBMS_SESSION.SET_CONTEXT( 'hr_ctx', 'id', 'robert', 'APPSMGR', 12345 );
    DBMS_SESSION.SET_CONTEXT( 'hr_ctx', 'dept', 'sales', 'APPSMGR', 12345 );
    
  8. AppSvrがこのセッションにデータベース接続を割り当て、次の文を発行してセッションを初期化します。

    DBMS_SESSION.SET_IDENTIFIER( 12345 );
    
  9. このデータベース・セッション内のすべてのSYS_CONTEXTコールが、そのクライアントのセッションのみに属するアプリケーション・コンテキストの値を戻します。

    たとえば、SYS_CONTEXT('hr','id')は、robertという値を戻します。

  10. セッションが終了すると、AppSvrは次の文を発行してクライアントの識別情報を消去します。

    DBMS_SESSION.CLEAR_IDENTIFIER ( );
    

他のユーザーがデータベースにログインした場合でも、このユーザーはAppSvrによって設定されたグローバル・コンテキストにはアクセスできません。これは、AppSvrが、ユーザーAPPSMGRがログインしたアプリケーションのみがこのグローバル・コンテキストを認識できるように指定したためです。AppSvrが次の文を使用した場合、クライアントIDが12345に設定されたあらゆるユーザー・セッションがグローバル・コンテキストを認識できるようになります。

DBMS_SESSION.SET_CONTEXT( 'hr_ctx', 'id', 'robert', NULL , 12345 );
DBMS_SESSION.SET_CONTEXT( 'hr_ctx', 'dept', 'sales', NULL , 12345 );

USERNAMENULLに設定すると、異なるユーザーが同一のコンテキストを共有できます。

ノート:

グローバル・コンテキストの設定が異なると、セキュリティ上の意味が変わることを認識する必要があります。ユーザー名にNULLが指定されている場合は、すべてのユーザーがそのグローバル・コンテキストにアクセスできます。グローバル・コンテキストのクライアントIDにNULLが指定されている場合、そのグローバル・コンテキストにアクセスできるのは、初期化されていないクライアントIDを持つセッションです。セッションへのアクセスをログインしたユーザーのみに制限するには、NULLのかわりにUSERを指定します。

セッションに設定されたクライアント識別子は、次のように問い合せることができます。

SELECT SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER') FROM DUAL;

次の出力が表示されます。

SYS_CONTEXT('USERENV','CLIENT_IDENTIFIER')
-------------------------------------------------
12345

セキュリティ管理者は、V$SESSIONビューのCLIENT_IDENTIFIERおよびUSERNAMEを問い合せることで、どのセッションにクライアント識別子が設定されているかを確認できます。たとえば:

COL client_identifier format a18
SELECT CLIENT_IDENTIFIER, USERNAME from V$SESSION;

次の出力が表示されます。

CLIENT_IDENTIFIER   USERNAME
------------------  --------
12345               APPSMGR

グローバル・コンテキストの使用領域(バイト単位)をチェックするには、次の問合せを使用します。

SELECT SYS_CONTEXT('USERENV','GLOBAL_CONTEXT_MEMORY') FROM DUAL;

次の出力が表示されます。

SYS_CONTEXT('USERENV','GLOBAL_CONTEXT_MEMORY')
----------------------------------------------
584

関連項目:

USERENVアプリケーション・コンテキストの事前定義属性であるCLIENT_IDENTIFIERの使用の詳細は、次を参照してください。

10.5 クライアント・セッション・ベースのアプリケーション・コンテキストの使用

クライアント・セッション・ベースのアプリケーション・コンテキストは、ユーザー・グローバル領域(UGA)に格納されます。

10.5.1 クライアント・セッション・ベースのアプリケーション・コンテキストについて

Oracle Call Interface (OCI)関数で、ユーザー・グローバル領域(UGA)のユーザー・セッション情報を設定およびクリアできます。

セッション・ベース・アプリケーション・コンテキストのこのタイプのアプリケーション・コンテキストの利点は、個々のアプリケーションが特定の非データベース・ユーザー・セッション・データを確認でき、このタスクをデータベースで実行しないことです。もう1つの利点は、アプリケーション・コンテキスト値を設定するコールはサーバーに対する次のコールに含まれるため、パフォーマンスが向上するという点です。

ただし、アプリケーション・コンテキストは、クライアント・セッション・ベースのアプリケーション・コンテキストではセキュリティを維持できなくなる点に注意が必要です。具体的には、アプリケーション・ユーザーがクライアント・アプリケーション・コンテキストを設定できるようになり、データベースでのチェックが一切実行されません。

クライアント・セッション・ベースのアプリケーション・コンテキストは、クライアント・アプリケーションに対してのみ構成します。クライアントの接続先データベース・サーバーには、設定を構成しません。データベース・サーバーのアプリケーション・コンテキスト設定は、クライアント・セッション・ベースのアプリケーション・コンテキストに影響を与えません。

クライアント・セッション・ベースのアプリケーション・コンテキストを構成するには、OCI関数OCIAppCtxSetを使用します。CLIENTCONTEXTネームスペースを使用するクライアント・セッション・ベースのアプリケーション・コンテキストは、OCIクライアントまたはアプリケーション・コンテキストの既存のDBMS_SESSIONパッケージで更新できます。このタイプのコンテキストでは、権限またはパッケージ・セキュリティのチェックは実行されません。

CLIENTCONTEXTネームスペースを使用すると、1つのアプリケーション・トランザクションで、ユーザー・コンテキスト情報を変更することと、同じユーザー・セッション・ハンドルを使用して新規ユーザー・リクエストに対応することの両方が可能になります。CLIENTCONTEXTネームスペースで属性の個々の値を設定またはクリアすることも、すべての値をクリアすることもできます。

  • OCIクライアントではOCIAppCtx関数を使用して、ネームスペースOCISessionHandleの可変長データを設定します。OCIネットワークの単一ラウンドトリップ転送は、1回のラウンドトリップで全情報をサーバーに送信します。サーバー側では、ネームスペースに対してSYS_CONTEXT SQL関数を使用することで、アプリケーション・コンテキスト情報を問い合せることができます。たとえば:

  • JDBCクライアントでは、oracle.jdbc.internal.OracleConnection関数を使用してこれと同じことを実行します。

CLIENTCONTEXTネームスペースはパッケージ・ベースのセキュリティで保護されていないため、すべてのユーザーがこのネームスペース内の情報を設定、クリアまたは収集できます。

関連項目:

クライアント・アプリケーション・コンテキストの詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』を参照してください。

10.5.2 CLIENTCONTEXTネームスペースへの値の設定

Oracle Call Interface (OCI)で、CLIENTCONTEXTネームスペースを設定できます。

  • CLIENTCONTEXTネームスペースに値を設定するには、次の構文でOCIAppCTXSetコマンドを使用します。

    err = OCIAppCtxSet((void *) session_handle,(dvoid *)"CLIENTCONTEXT",(ub4) 13,
                       (dvoid *)attribute_name, length_of_attribute_name 
                       (dvoid *)attribute_value, length_of_attribute_value, errhp,
                       OCI_DEFAULT);
    

詳細は、次のとおりです。

  • session_handleは、OCISessionHandleネームスペースを表します。

  • attribute_nameは、属性の名前です。たとえば、長さ14responsibilityを指定します。

  • attribute_valueは、属性の値です。たとえば、長さ7managerを指定します。

関連項目:

OCIAppCtxファンクションの詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照してください

10.5.3 CLIENTCONTEXTネームスペースの取得

Oracle Call Interfaceを使用して、CLIEINTCONTEXTネームスペースを取得できます。

  • CLIENTCONTEXTネームスペースを取得するには、次のいずれかの文でOCIStmtExecuteコールを使用します。

    • SELECT SYS_CONTEXT('CLIENTCONTEXT', 'attribute-1') FROM DUAL;

    • SELECT VALUE FROM SESSION_CONTEXT WHERE NAMESPACE='CLIENTCONTEXT' AND ATTRIBUTE='attribute-1';

attribute-1の値は、CLIENTCONTEXTネームスペースですでに設定されているどんな属性値でも構いません。Oracle Databaseは設定された属性のみを取得します。設定済属性がない場合は、NULLを返します。通常、属性を設定するにはOCIAppCtxSetコールを使用します。さらに、DBMS_SESSION.SET_CONTEXTコールをOCIコードに埋め込んで属性値を設定できます。

10.5.4 例: クライアント・セッション・ベース・コンテキストのクライアント・セッションID値の取得

OCI OCIStmtExecuteコールで、クライアント・セッション・ベース・コンテキストのクライアント・セッションID値を取得できます。

例10-10に、OCIStmtExecuteコールを使用してクライアント・セッションIDを取得する方法を示します。

例10-10 クライアント・セッション・ベース・コンテキストのクライアント・セッションID値の取得

oratext    clientid[31];
OCIDefine  *defnp1 = (OCIDefine *) 0;
OCIStmt    *statementhndle;
oratext    *selcid = (oratext *)"SELECT SYS_CONTEXT('CLIENTCONTEXT',
            attribute) FROM  DUAL"; 
 
OCIStmtPrepare(statementhndle, errhp, selcid, (ub4) strlen((char *) selcid),
  (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); 
 
OCIDefineByPos(statementhndle, &defnp1, errhp, 1, (dvoid *)clientid, 31,
  SQLT_STR, (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, OCI_DEFAULT);
 
OCIStmtExecute(servhndle, statementhndle, errhp, (ub4) 1, (ub4) 0,
  (CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT);

 printf("CLIENT_IDENTIFIER = %s \n", clientid);

この例では、次のようになります。

  • oratextOCIDefineOCIStmtおよびoratextは、クライアント・セッションID、OCIDefineの参照コール、文ハンドルおよび使用するSELECT文を格納するための変数を作成します。

  • OCIStmtPrepareは、文selcidを実行する準備を整えます。

  • OCIDefineByPosは、クライアント・セッションIDの出力変数clientidを定義します。

  • OCIStmtExecuteは、selcid変数に格納されている文を実行します。

  • printfは、取得したクライアント・セッションIDに書式を設定した出力を表示します。

10.5.5 CLIENTCONTEXTネームスペースの設定のクリア

Oracle Call Interfaceを使用して、CLIENTCONTEXTネームスペースをクリアできます。

  • CLIENTCONTEXTの設定をクリアするには、次のいずれかのコマンドを使用して、値をNULLまたは空の文字列に設定します。

    • 次のコマンドは、空の文字列をゼロに設定します。

      (void) OCIAppCtxSet((void *) session_handle, (dvoid *)"CLIENTCONTEXT", 13,
                         (dvoid *)attribute_name, length_of_attribute_name, 
                         (dvoid *)0, 0,errhp
                         OCI_DEFAULT);
      
    • 次のコマンドは、空の文字列を空白値に設定します。

      (void) OCIAppCtxSet((void *) session_handle, (dvoid *)"CLIENTCONTEXT", 13
                         (dvoid *)attribute_name, length_of_attribute_name, 
                         (dvoid *)"", 0,errhp,
                         OCI_DEFAULT);

10.5.6 CLIENTCONTEXTネームスペースのすべての設定のクリア

Oracle Call Interface (OCI)を使用して、CLIENTCONTEXTネームスペースをクリアできます。

  • ネームスペースを消去するには、次の構文でOCIAppCtxClearAllコマンドを使用します。

    err = OCIAppCtxClearAll((void *) session_handle, 
                           (dvoid *)"CLIENTCONTEXT", 13,
                            errhp,                        OCI_DEFAULT);
     

10.6 アプリケーション・コンテキストのデータ・ディクショナリ・ビュー

Oracle Databaseには、アプリケーション・コンテキストに関する情報を提供するデータ・ディクショナリ・ビューが用意されています。

表10-3に、これらのデータ・ディクショナリ・ビューを示します。

表10-3 アプリケーション・コンテキストに関する情報を表示するデータ・ディクショナリ・ビュー

ビュー 説明

ALL_CONTEXT

属性および値がDBMS_SESSION.SET_CONTEXTプロシージャを使用して指定された、カレント・セッション内のすべてのコンテキスト・ネームスペースが表示されます。ネームスペースと、対応付けられているスキーマおよびPL/SQLパッケージがリストされます。

ALL_POLICY_CONTEXTS

現行ユーザーがアクセス可能なシノニム、表およびビューに定義されている駆動コンテキストが表示されます。(駆動コンテキストは、仮想プライベート・データベース・ポリシーで使用されるコンテキストです。)

DBA_CONTEXT

データベース内のすべてのコンテキスト・ネームスペース情報が表示されます。このビューの列は、TYPE列が含まれていること以外はALL_CONTEXTビューの各列と同じです。TYPE列には、アプリケーション・コンテキストのアクセスまたは初期化の方法が表示されます。

DBA_OBJECTS

既存のアプリケーション・コンテキストの名前が表示されます。次のように、DBA_OBJECTSビューのOBJECT_TYPE列を問い合せます。

SELECT OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_TYPE ='CONTEXT';

DBA_POLICY_CONTEXTS

DBMS_RLS.ADD_POLICY_CONTEXTプロシージャによってデータベースに追加されたすべての駆動コンテキストが表示されます。このビューの列は、ALL_POLICY_CONTEXTSの各列と同じです。

SESSION_CONTEXT

カレント・セッションに設定されているコンテキスト属性とその値が表示されます。

USER_POLICY_CONTEXTS

現行ユーザーが所有するシノニム、表およびビューに定義されている駆動コンテキストが表示されます。このビューの列は、OBJECT_OWNER列以外はALL_POLICY_CONTEXTSの各列と同じです。

V$CONTEXT

カレントPDBセッションに設定されている属性がリストされます。このビューに対するSELECT権限が付与されていないユーザーは、このビューにアクセスできません。

V$SESSION

各カレントPDBセッションに関する詳細情報がリストされます。このビューに対するSELECT権限が付与されていないユーザーは、このビューにアクセスできません。

ヒント:

アプリケーション・コンテキストを使用するアプリケーションの実行時にエラーが発生した場合は、これらのビューに加え、データベース・トレース・ファイルも確認してください。USER_DUMP_DEST初期化パラメータは、トレース・ファイルのディレクトリの場所を示します。このパラメータの値は、SQL*PlusでSHOW PARAMETER USER_DUMP_DESTを発行して確認できます。

関連項目: