プライマリ・コンテンツに移動
Oracle® Databaseセキュリティ・ガイド
11gリリース2 (11.2)
B56285-13
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

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

この章の内容は、次のとおりです。

アプリケーション・コンテキストの概要

この項の内容は、次のとおりです。

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

アプリケーション・コンテキストとは、Oracle Databaseがメモリーに格納する名前と値のペアです。アプリケーション・コンテキストには、ネームスペースと呼ばれるラベル(たとえば、従業員IDを取得するアプリケーション・コンテキストはempno_ctx)があります。コンテキスト内は名前と値のペア(結合配列)です。名前は、を保持するメモリー内の場所を指定します。アプリケーションはアプリケーション・コンテキストを使用して、ユーザーに関するセッション情報(ユーザーIDまたは他のユーザー固有の情報など)またはクライアントIDにアクセスして、その情報をデータベースに安全に引き渡すことができます。この情報を使用して、ユーザーがアプリケーションを通じてデータにアクセスできるようにしたりアクセスできないようにできます。アプリケーション・コンテキストを使用して、データベース・ユーザーと非データベース・ユーザーの両方を認証できます。

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

名前と値のペアの構成要素は、次のとおりです。

  • 名前:値に関連付けられている属性セットの名前を示します。たとえば、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)コールを使用してアプリケーション・コンテキストを設定することもできます。

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

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

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

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

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

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

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

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

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

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

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

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

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


関連項目:

エディションの詳細は、『Oracle Databaseアドバンスト・アプリケーション開発者ガイド』を参照してください。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

あり

なし

なし

なし

なし

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

あり

なし

あり

なし

なし

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

あり

なし

なし

あり

なし

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

なし

あり

なし

なし

あり

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

あり

なし

あり

なし

あり


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

この項の内容は、次のとおりです。

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

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


注意:

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

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

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

データベース・セッション・ベースのアプリケーション・コンテキストを作成して使用するには、次のコンポーネントを使用します。

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

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

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

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

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

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

データベース・セッション・ベースのアプリケーション・コンテキストを作成するには、CREATE CONTEXT SQL文を使用します。ここで、アプリケーション・コンテキストのネームスペースを作成してから、ユーザーのセッション情報を保持する名前と値のペアを管理するPL/SQLパッケージに関連付けます。この文を実行するために、CREATE ANY CONTEXTシステム権限が必要です。アプリケーション・コンテキストを削除する場合は、DROP CONTEXT文を使用するためにDROP ANY CONTEXT権限が必要になります。データベース・セッション・ベースのアプリケーション・コンテキストでは、データはデータベース・ユーザー・セッション(UGA)のネームスペース内に保管され、これはCREATE CONTEXT SQL文を使用して作成されます。

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

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

例6-1に、CREATE CONTEXTを使用してデータベース・セッション・ベースのアプリケーション・コンテキストを作成する方法を示します。

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

CREATE CONTEXT empno_ctx USING set_empno_ctx_pkg;

ここで、empno_ctxはコンテキスト・ネームスペース、set_empno_ctx_pkgはそのempno_ctxネームスペースの属性を設定するパッケージです。PL/SQLパッケージは、アプリケーション・コンテキストの作成時には不要ですが、実行時には存在している必要があります。このアプリケーション・コンテキストで使用可能なパッケージの作成方法の例は、「手順3: セッション・データを取得してアプリケーション・コンテキストを設定するパッケージの作成」を参照してください。

コンテキストを作成するときは、そのコンテキストの名前/値の属性をCREATE CONTEXT文に設定しないでください。これらの属性は、アプリケーション・コンテキストに関連付けるパッケージに設定してください。これは、不正なユーザーによって、適切な属性の検証なしにコンテキスト属性が変更されないようにするためです。


注意:

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

各アプリケーションには、独自の属性を持つアプリケーション・コンテキストを作成できます。たとえば、General Ledger(一般会計)、Order Entry(受注管理)およびHuman Resources(人事管理)という3つのアプリケーションがあるとします。これらの各アプリケーションには、異なる属性を指定できます。

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

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

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

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

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

この項の内容は、次のとおりです。

データベース・セッション・ベースのアプリケーション・コンテキストを管理するパッケージの概要

PL/SQLパッケージは、通常、セキュリティ管理者のスキーマに作成され、アプリケーション・コンテキストによって表されるセッション・データを管理するプロシージャを定義します。次のタスクを実行する必要があります。

  • セッション情報の取得。ユーザー・セッション情報の取得には、SYS_CONTEXT SQL関数を使用できます。このSYS_CONTEXT関数は、コンテキストのネームスペースに関連付けられているパラメータの値を戻します。この関数は、SQL文とPL/SQL文の両方で使用できます。通常は、組み込まれているUSERENVネームスペースを使用してユーザーのセッション情報を取得します。(SYS_CONTEXT関数の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。)

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

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

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

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

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

データベース・セッション・ベースのアプリケーション・コンテキストの作成方法は、「例: データベース・セッション・ベースのアプリケーション・コンテキストの作成と使用」を参照してください。

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

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

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

次のように値を指定します。

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

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

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

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

たとえば、次のようにUSERENVHOSTパラメータを使用して、クライアントが接続しているホスト・コンピュータの名前を取得できます。

SYS_CONTEXT ('userenv','host')

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

例6-2では、ログインしたホスト・コンピュータの検索方法を示しています。この例では、EMP_USERSの下のSHOBEEN_PCホスト・コンピュータにログインしたと想定しています。

例6-2 SYS_CONTEXT値の検索

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

SYS_CONTEXT(USERENV,HOST)
-------------------------
EMP_USERS\SHOBEEEN_PC

注意:

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

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述語の形で表され、述語はポリシーとみなされます。述語が変更された場合、正しい結果を生成するために文を再度解析する必要があります。

パラレル問合せでの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;

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

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

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

リモートのPL/SQLプロシージャ・コールがデータベース・リンクで実行されている場合は、そのプロシージャ内部のすべてのSYS_CONTEXT関数が、そのリンクの宛先データベースで実行されます。この場合、データベース・リンクの宛先サイトで使用できるのは、外部で初期化されたアプリケーション・コンテキストのみです。セキュリティ上の理由から、データベース・リンクの開始サイトから宛先サイトに伝播されるのは、外部で初期化されたアプリケーション・コンテキストのみです。

DBMS_SESSION.SET_CONTEXTを使用したセッション情報の設定

SYS_CONTEXT関数を使用してユーザーのセッション・データを取得後、アプリケーション・コンテキスト値をこのユーザーのセッションから設定できます。そのためには、DBMS_SESSION.SET_CONTEXTプロシージャを使用します。(DBMS_SESSION PL/SQLパッケージに対するEXECUTE権限を所有していることを確認してください。)

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

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が使用されます。

DBMS_SESSIONパッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

例6-1で作成したアプリケーション・コンテキストを例にします。

CREATE CONTEXT empno_ctx USING set_empno_ctx_proc;

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

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

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属性の値を指定します。ここでは2行目に定義されている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

関連項目:


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

アプリケーション・コンテキストと関連のパッケージを作成した後は、ユーザーはログイン時にそのパッケージ・プロシージャを実行する必要があります。これを自動的に処理するようにログイン・トリガーを作成できます。パッケージを実行するためのEXECUTE権限をユーザーに付与する必要はありません。

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

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

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

例6-5は、WHEN OTHERS例外を使用するログイン・トリガーの作成方法を示しています。一方、PL/SQLロジックにエラーが発生して未処理例外を引き起こす場合は、データベースへのすべての接続がブロックされます。この例は、セキュリティ管理者のスキーマの表にエラーを書き込むWHEN OTHERS例外を示しています。本番環境では、こちらのほうが、出力をユーザー・セッションへ送信することでセキュリティ攻撃を受けやすくなるよりも安全です。

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

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;
/

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

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

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;
/

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

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

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

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


注意:

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

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

この項の内容は、次のとおりです。

このチュートリアルの概要

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

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

  1. ユーザーSYSでログインし、AS SYSDBA権限を使用して接続します。

    sqlplus sys as sysdba
    Enter password: password
    
  2. sysadmin_ctxアカウントを作成します。このアカウントは、データベース・セッション・ベースのアプリケーション・コンテキストを管理します。

    GRANT CREATE SESSION, CREATE ANY CONTEXT, CREATE PROCEDURE, CREATE TRIGGER, ADMINISTER DATABASE TRIGGER TO sysadmin_ctx IDENTIFIED BY password;
    GRANT SELECT ON HR.EMPLOYEES TO sysadmin_ctx;
    GRANT EXECUTE ON DBMS_SESSION TO sysadmin_ctx;
    

    passwordを安全なパスワードに置き換えます。詳細は、「パスワードの最低要件」を参照してください。

  3. Lisa Ozerに対して、次のユーザー・アカウントを作成します。HR.EMPLOYEES表には、lozerというLisa Ozerの電子メール・アカウントがあります。

    GRANT CREATE SESSION TO LOZER IDENTIFIED BY password;
    

    passwordを安全なパスワードに置き換えます。詳細は、「パスワードの最低要件」を参照してください。

  4. この例ではサンプル・ユーザーSCOTTも使用するため、DBA_USERSデータ・ディクショナリ・ビューを問い合せて、SCOTTがロックされていたり、期限切れになっていないことを確認します。

    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アカウントに指定しないでください。パスワードを作成するための最低要件は、「パスワードの最低要件」を参照してください。

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

  1. sysadmin_ctxでSQL*Plusにログインします。

    CONNECT sysadmin_ctx
    Enter password: password
    
  2. 次の文を使用してアプリケーション・コンテキストを作成します。

    CREATE CONTEXT empno_ctx USING set_empno_ctx_pkg;
    

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

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

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

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

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変数に格納された値に設定します。emp_id変数は8行目で作成され、従業員IDは10から11行目で取得されます。

    要約すると、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表にリストされたユーザーを除き、システム管理者以外のユーザーはデータベースにログインできなくなります。他のユーザーは、有効なデータベース・ユーザーであればデータベースにログインできます。アプリケーション・コンテキスト情報が設定された後は、特定のアプリケーションへのユーザー・アクセスを制御する手段として、このセッション情報を使用できます。

手順4: パッケージに対するログイン・トリガーの作成

ユーザーsysadmin_ctxで、次のトリガーを作成します。

CREATE TRIGGER set_empno_ctx_trig AFTER LOGON ON DATABASE
 BEGIN
  sysadmin_ctx.set_empno_ctx_pkg.set_empno;
 END;
/

手順5: アプリケーション・コンテキストのテスト

  1. ユーザーlozerでログインします。

    CONNECT lozer
    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
    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を使用できます。詳細は、第7章「Oracle Virtual Private Databaseを使用したデータ・アクセスの制御」を参照してください。

手順6: この例で使用したコンポーネントの削除

  1. SYSでログインし、AS SYSDBAを使用して接続します。

    CONNECT SYS/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; 
    

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

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

この項の内容は、次のとおりです。

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

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

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

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

他の外部リソースからの値の取得

外部リソースを介して属性と値の初期化を受け入れるアプリケーション・コンテキストを作成できます。このような外部リソースには、OCIインタフェース、ジョブ・キュー・プロセスまたはデータベース・リンクなどが含まれます。

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

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

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

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

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

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

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

CREATE CONTEXT ext_ctx USING ext_ctx_pkg INITIALIZED EXTERNALLY;

中間層サーバーからのアプリケーション・コンテキスト値の初期化

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

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

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


関連項目:

  • プロキシ認証の詳細およびUSERENV属性CLIENT_IDENTIFIERを使用して複数層にわたってユーザー識別情報を保持する方法は、「複数層環境でのユーザー識別情報の保持」を参照してください。

  • セキュア・アプリケーション・ロールを使用して特定のプロキシを経由するようにポリシーを規定する方法は、「中間層サーバーを使用したプロキシ認証」を参照してください。

  • 『Oracle Database JDBC開発者ガイド』

  • 『Oracle Call Interfaceプログラマーズ・ガイド』


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

この項の内容は、次のとおりです。

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

ユーザーのデータベース・セッション・ベースのアプリケーション・コンテキストは、集中格納場所を使用して格納できます。これによって、アプリケーションでは、初期化中にユーザーの識別情報に基づいてユーザー・コンテキストを設定できます。特に、この機能では、Oracle Label Securityのラベルと権限がサポートされます。アプリケーション・コンテキストをグローバルに初期化すると、多数のユーザーとデータベースのコンテキストを簡単に管理できます。

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

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

グローバルに初期化されたアプリケーション・コンテキストは、拡張可能で効率的な標準ディレクトリ・アクセス・プロトコルであるLDAPを使用します。LDAPディレクトリには、このアプリケーションが割り当てられているユーザーのリストが格納されます。Oracle Databaseでは、ディレクトリ・サービス(通常はOracle Internet Directory)を使用して、エンタープライズ・ユーザーを認証および認可します。


注意:

  • エンタープライズ・ユーザー・セキュリティを使用するにはOracle Advanced Securityが必要です。

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


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

LDAPオブジェクトinetOrgPersonにより、一部の属性では複数のエントリが存在可能です。ただし、これらのエントリがデータベースにロードされ、SYS_LDAP_USER_DEFAULTコンテキスト・ネームスペースでアクセスされると、これらのエントリのうち最初のエントリだけが返されます。たとえば、ユーザーに対するinetOrgPersonオブジェクトでは、telephoneNumberに複数のエントリが可能です(そのため、ユーザーは複数の電話番号を保存できます)。SYS_LDAP_USER_DEFAULTコンテキスト・ネームスペースを使用すると、最初の電話番号だけが取得されます。

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

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

図6-1の説明を次に示します
「図6-1 LDAPディレクトリの情報ツリーにおけるアプリケーション・コンテキストの位置」の説明

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

グローバルに初期化されたセキュア・アプリケーションを使用するには、Oracle Advanced Securityの機能の1つであるエンタープライズ・ユーザー・セキュリティを最初に構成する必要があります。次に、ユーザーのアプリケーション・コンテキスト値をデータベースとディレクトリに設定します。

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


関連項目:

エンタープライズ・ユーザー・セキュリティの構成の詳細は、『Oracle Databaseエンタープライズ・ユーザー・セキュリティ管理者ガイド』を参照してください。

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

ユーザーの初期アプリケーション・コンテキスト(部門名や職位など)は、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エントリの例を示します。

    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
    

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

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


注意:

エンタープライズ・ユーザー・セキュリティはOracle Advanced Securityの機能です。


関連項目:


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

この項の内容は、次のとおりです。

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

グローバル・アプリケーション・コンテキストにより、Oracle RACインスタンスを含むデータベース・セッションでアプリケーション・コンテキスト値にアクセス可能になります。グローバル・アプリケーション・コンテキスト情報はシステム・グローバル領域(SGA: 共有グローバル領域でSGAと称する場合もあります)に格納されるため、3層アーキテクチャの中間層アプリケーションなど、セッションを使用しないアプリケーションに対して使用できます。このようなアプリケーションでは、複数のユーザーがアプリケーションに対して認証され、通常は単一の識別情報としてデータベースに接続するため、セッション・ベースのアプリケーション・コンテキストを使用できません。グローバル・アプリケーション・コンテキストは、ユーザー・セッション単位ではなく一度に初期化されます。したがって、接続は接続プールから再利用されるため、パフォーマンスが向上します。

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

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

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

  • 非データベース・ユーザー(つまり、データベースに認識されていないユーザー)を認証する必要がある場合。データベース・アカウントを持たないこのタイプのユーザーは、通常、Webアプリケーション経由で接続プールを使用して接続します。このようなアプリケーションでは、One Big Application User認証モデルを使用して、複数のユーザーを単一のユーザーとしてデータベースに接続します。このタイプのユーザーを認証するには、そのユーザーのクライアント・セッション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設定で値を上書きできることに注意してください。詳細は、「DBMS_SESSION PL/SQLパッケージを使用したクライアント識別子の設定と消去」を参照してください。

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

Oracle RAC環境では、グローバル・アプリケーション・コンテキストがロードまたは変更された場合は、常に、既存のアクティブ・インスタンスによってのみ、そのことが認識されます。Oracle RAC環境でグローバル・アプリケーション・コンテキスト値を設定すると、コンテキスト値をすべてのOracle RACインスタンスに一貫して伝播することによるパフォーマンスのオーバーヘッドが生じることに注意してください。

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

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

グローバル・アプリケーション・コンテキストを作成するには、CREATE CONTEXT SQL文を使用してグローバル・アプリケーション・コンテキストを作成し、ACCESSED GLOBALLY句をこのSQL文に含めます。CREATE CONTEXT文を使用するにはCREATE ANY CONTEXTシステム権限が必要であり、DROP CONTEXT文でコンテキストを削除するにはDROP ANY CONTEXT権限が必要になります。ローカル・アプリケーション・コンテキストと同様、グローバル・アプリケーション・コンテキストもセキュリティ管理者のデータベース・スキーマで作成および格納されます。

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

例6-9に、グローバル・アプリケーション・コンテキストglobal_hr_ctxの作成方法を示します。このコンテキストは、hr_ctx_pkgパッケージを使用して設定されます。

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

CREATE OR REPLACE CONTEXT global_hr_ctx USING hr_ctx_pkg ACCESSED GLOBALLY;

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

この項の内容は、次のとおりです。

DBMS_SESSIONパッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

グローバル・アプリケーション・コンテキストを管理するパッケージの概要

グローバル・アプリケーション・コンテキストに関連付けるPL/SQLパッケージのタスクは、DBMS_SESSIONパッケージを使用したグローバル・アプリケーション・コンテキスト値の設定と消去です。このプロシージャを使用するには、DBMS_SESSIONパッケージに対するEXECUTE権限が必要です。通常、このパッケージはセキュリティ管理者のデータベース・スキーマに作成および格納されます。DBMS_SESSIONパッケージはSYSスキーマの所有です。

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

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

エディションがグローバル・アプリケーション・コンテキストの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アドバンスト・アプリケーション開発者ガイド』を参照してください。

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

DBMS_SESSION.SYS_CONTEXTプロシージャには、namespaceattributeおよびvalueパラメータの他に、client_idパラメータとusernameパラメータも用意されています。これらの設定はグローバル・アプリケーション・コンテキストに使用します。これらの設定の組合せによって、作成可能なグローバル・アプリケーション・コンテキストのタイプがどのように制御されるかについて、表6-2で説明します。

表6-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言語リファレンス』を参照してください。

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


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

全データベース・ユーザーを対象としてグローバル・アプリケーションの値を共有するには、SET_CONTEXTプロシージャのnamespaceattributeおよびvalueパラメータを設定します。このシナリオでは、データベース・アカウントを持つすべてのユーザーが、そのデータベース内のデータにアクセスできる可能性があります。

例6-10に、このタイプのグローバル・アプリケーション・コンテキストを設定および消去するパッケージの作成方法を示します。

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

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プロシージャを使用して、namespace、attributeおよびvalueパラメータの値を設定します。sec_level値は、データベース・アプリケーションがhr_ctx_pkg.set_hr_ctxプロシージャを実行する際に指定されます。

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

  • namespace => 'global_hr_ctx'は、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
-----------

注意:

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

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

EXEC DBMS_SESSION.CLEAR_IDENTIFIER;

複数のアプリケーション間を移動するデータベース・ユーザーに対するグローバル・コンテキストの設定

複数のアプリケーション間を移動するデータベース・ユーザーに対してグローバル・アプリケーション・コンテキストを設定する場合、特に、移動する複数のアプリケーション間でアクセス要件が異なる場合は、SET_CONTEXTプロシージャにusernameパラメータを指定します。このパラメータは、すべてのセッションを対象として同じスキーマを使用することを指定します。

次のSET_CONTEXTパラメータを使用します。

  • namespace

  • attribute

  • value

  • username

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

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

例6-11に、特定のユーザーが複数のアプリケーション間を移動できるように、usernameパラメータを設定する方法を示します。この例は、例6-10で作成したパッケージに類似しています。usernameパラメータを使用している部分は、太字で記載しています。

例6-11 複数のアプリケーション間を移動するユーザーのグローバル・アプリケーション・コンテキスト値を管理するためのパッケージ

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権限を指定する必要があります。つまり、アプリケーション(ユーザーではなく)がユーザーのコンテキストを設定します。

非データベース・ユーザーに対するグローバル・アプリケーション・コンテキストの設定

非データベース・ユーザー、つまり、データベースに認識されていないユーザー(Webアプリケーション・ユーザーなど)がクライアント・セッションを開始すると、アプリケーション・サーバーによってクライアント・セッションIDが生成されます。この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

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

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

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プロシージャを作成します。33行目: 正しいセッションID、つまり10行目で定義されている変数session_id_pに格納されているIDを消去するように設定します。

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


関連項目:


セッションをクローズする際のセッション・データの消去

アプリケーション・コンテキストは、すべてがメモリー内に存在します。ユーザーがセッションを終了したときは、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ファンクションによって値を取得する後続のコールでは、最新の値が戻されます。

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

この項の内容は、次のとおりです。

中間層アプリケーションを使用したクライアント・セッションIDの管理の概要

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

アプリケーションによってユーザーが認証され、クライアント識別子が設定されてカレント・セッションに設定されます。PL/SQLパッケージSET_CONTEXTによって、アプリケーション・コンテキストにclient_identifier値が設定されます。詳細は、「非データベース・ユーザーに対するグローバル・アプリケーション・コンテキストの設定」を参照してください。

中間層アプリケーションを使用したクライアント・セッション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';

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

例6-13 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に書式を設定した出力を表示します。

中間層アプリケーションを使用したクライアント・セッション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を設定します。この設定によって、セッションは異なるグローバル・アプリケーション・コンテキストの値セットを使用するようになります。

次の方法を使用して、アプリケーション・サーバー側にクライアント・セッション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 Advanced Securityを使用して暗号化できます。詳細は、『Oracle Database Advanced Security管理者ガイド』を参照してください。ネットワークを介したデータの暗号化については、『Oracle Database 2日でセキュリティ・ガイド』を参照してください。


OCIAttrSetおよびDBMS_SESSION.SET_IDENTIFIERでは、次のようにして、この識別子の値をチェックできます。

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

この値をチェックする他の方法には、V$SESSIONビューを問い合せる方法があります。

SELECT CLIENT_IDENTIFIER from V$SESSION;

中間層アプリケーションを使用したセッション・データの消去

アプリケーション・コンテキストは、すべてがメモリー内に存在します。ユーザーがセッションを終了したときは、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を使用してください。

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

この項の内容は、次のとおりです。

このチュートリアルの概要

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

手順1: ユーザー・アカウントの作成

この例では、2人のユーザー(アプリケーション・コンテキストとそのパッケージを管理するセキュリティ管理者と、接続プールを所有するユーザー・アカウント)を作成する必要があります。

手順は、次のとおりです。

  1. SYSでSQL*Plusにログインし、AS SYSDBAを使用して接続します。

    sqlplus sys as sysdba
    Enter password: password
    
  2. sysadmin_ctxアカウントを作成します。このアカウントは、グローバル・アプリケーション・コンテキストを管理します。

    GRANT CREATE SESSION, CREATE ANY CONTEXT, CREATE PROCEDURE TO sysadmin_ctx IDENTIFIED BY password;
    
    GRANT EXECUTE ON DBMS_SESSION TO sysadmin_ctx;
    

    passwordを安全なパスワードに置き換えます。詳細は、「パスワードの最低要件」を参照してください。

  3. 接続プールの所有者にするデータベース・アカウントapps_userを作成します。

    GRANT CREATE SESSION TO apps_user IDENTIFIED BY password;
    

    passwordを安全なパスワードに置き換えます。詳細は、「パスワードの最低要件」を参照してください。

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

  1. セキュリティ管理者sysadmin_ctxでログインします。

    CONNECT sysadmin_ctx
    Enter password: password
    
  2. cust_ctxグローバル・アプリケーション・コンテキストを作成します。

    CREATE CONTEXT global_cust_ctx USING cust_ctx_pkg ACCESSED GLOBALLY;
    

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

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

  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;
    /
    

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

  2. cust_ctx_pkgパッケージに対するEXECUTE権限を接続プール所有者apps_userに付与します。

    GRANT EXECUTE ON cust_ctx_pkg TO apps_user;
    

手順4: グローバル・アプリケーション・コンテキストのテスト

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

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

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

    BEGIN
     sysadmin_ctx.cust_ctx_pkg.set_session_id(34256);
    END;
    /
    

    クライアント・セッション識別子の値は、次のようにテストしてチェックできます。

    1. 接続プール・ユーザーapps_userでSQL*Plusに接続します。

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

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

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

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

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

    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でクライアント・セッション識別子を設定した方法と同様に、中間層アプリケーションでグローバル・アプリケーション・コンテキスト値を設定することになります。)

  4. 次の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
-------------  --------------

次に、次のテストを試してください。

  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は適切に設定されていますが、アプリケーション・コンテキストの設定はすでに存在していません。これで、以前に設定したアプリケーション・コンテキストの値を使用せずに、このユーザーのセッションを続行できます。

手順5: この例で使用したコンポーネントの削除

  1. SYSでログインし、AS SYSDBAを使用して接続します。

    CONNECT sys/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;
    

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

この項の内容は、次のとおりです。

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

クライアント識別子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のアプリケーション・コンテキストのみが取得されます。

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

次の手順は、軽量ユーザー・アプリケーション用のグローバル・アプリケーション・コンテキスト・プロセスを示しています。軽量ユーザー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の使用の詳細は、次を参照してください。

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

この項の内容は、次のとおりです。

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

クライアント・セッション・ベースのアプリケーション・コンテキストでは、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プログラマーズ・ガイド』を参照してください。

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

Oracle Call Interfaceの場合、CLIENTCONTEXTネームスペースに値を設定するには、次の構文に従ってコマンドを使用します。

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プログラマーズ・ガイド』のスケーラブル・プラットフォームの管理に関する項を参照してください。

CLIENTCONTEXTネームスペースの取得

CLIENTCONTEXTネームスペースを取得するには、次のいずれかの文でOracle Call Interface 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コードに埋め込んで属性値を設定できます。

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

例6-14 クライアント・セッション・ベース・コンテキストのクライアント・セッション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に書式を設定した出力を表示します。

CLIENTCONTEXTネームスペースの設定の消去

Oracle Call Interfaceの場合、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);

CLIENTCONTEXTネームスペースのすべての設定の消去

Oracle Call Interface(OCI)の場合は、次の書式のコマンドを使用します。

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

アプリケーション・コンテキストに関する情報の検索

表6-3に、アプリケーション・コンテキストに関する情報の検索で問合せ可能なデータ・ディクショナリ・ビューをリストします。これらのビューの詳細は、『Oracle Databaseリファレンス』を参照してください。

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

ビュー 説明

ALL_CONTEXT

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

ALL_POLICY_CONTEXTS

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

DBA_CONTEXT

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

DBA_POLICY_CONTEXTS

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

SESSION_CONTEXT

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

USER_POLICY_CONTEXTS

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

V$CONTEXT

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

V$SESSION

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



ヒント:

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