ヘッダーをスキップ
Oracle Databaseセキュリティ・ガイド
11g リリース1(11.1)
E05730-05
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

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

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

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

アプリケーション・コンテキストは、Oracle Databaseによってメモリーに格納される一連の名前と値のペアです。アプリケーション・コンテキストには、ネームスペースと呼ばれるラベルが付いています。たとえば、従業員IDを取得するアプリケーション・コンテキストの場合はempno_ctxなどです。コンテキスト内は、名前と値のペア(連想配列)になっています。名前は、が保持されているメモリー内の位置を指します。アプリケーションは、アプリケーション・コンテキストを使用してユーザーに関するセッション情報(ユーザーIDや他のユーザー固有の情報など)またはクライアントIDにアクセスして、その情報をデータベースに安全に引き渡すことができます。その後は、この情報を使用して、ユーザーに対して、アプリケーションを介したデータへのアクセスを許可または防止できます。 アプリケーション・コンテキストを使用して、データベース・ユーザーと非データベース・ユーザーの両方を認証できます。

アプリケーション・コンテキストの名前と値のペアの構成要素

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

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

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

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

アプリケーション・コンテキストの用途

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

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

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

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

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

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

アプリケーション・コンテキストの所有権は、次のようになります。CREATE ANY CONTEXT権限とDROP ANY CONTEXT権限が付与されているユーザーは、アプリケーション・コンテキストを作成および削除できますが、その所有権は、SYSスキーマが所有します。コンテキストは、作成元のスキーマ・アカウントに関連付けられますが、このユーザーを削除した場合も、コンテキストは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ネームスペースを使用してユーザーのセッション情報を取得します。

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

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

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

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

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

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

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

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

  • namespace: アプリケーション・コンテキストの名前。文字列または式を指定できます。

  • parameter: namespaceアプリケーション・コンテキスト内のパラメータ。

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

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

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

SYS_CONTEXT ('userenv','host')

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

例6-2に、ログインしているホスト・コンピュータの検索方法を示します。ここでは、EMP_USERSの下のSHOBEEEN_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の使用

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

ユーザー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バイト以内です。たとえば、empno_ctxというネームスペースを使用する場合は、次のように指定します。

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

    attribute => 'ctx_attrib',
    
  • value: 設定するアプリケーション・コンテキストの値。4000バイト以内です。通常、この値はSYS_CONTEXT関数によって取得され、変数に格納されます。次に例を示します。

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

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

  • 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 アプリケーション・コンテキストの値を作成する単純なプロシージャ

1
2
3
4
5
6
7
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;
/

この例の説明は、次のとおりです。

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

  • 5行目: 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でログインしていることを確認してください。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 NUMBER;
   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というプロシージャが作成されます。

  • 8行目: 変数emp_idを宣言します。この変数には、ログインするユーザーの従業員IDが格納されます。

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

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

  • 12行目: 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および電子メール・アドレスと照合する」プロシージャです。

  • 13–14行目: WHEN NO_DATA_FOUNDシステム例外を追加して、10–11行目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
    Connected.
    

    ユーザー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またはThick JDBC経由の軽量ユーザー・セッションを作成する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社のSunONEなどのサード・パーティ製ディレクトリもディレクトリ・サービスとして使用できます。


LDAPオブジェクトorclDBApplicationContextgroupOfUniqueNamesのサブクラス)は、アプリケーション・コンテキスト値をディレクトリに格納します。図6-1に、アプリケーション・コンテキスト・オブジェクトの位置を示します。この図は人事管理の例に基づいています。

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の機能です。


関連項目:


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

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

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

グローバル・アプリケーション・コンテキストを使用すると、アプリケーション・コンテキスト値を複数のデータベース・セッションにわたってアクセス可能にできます。グローバル・アプリケーション・コンテキスト情報はシステム・グローバル領域(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パッケージを使用したクライアント識別子の設定と消去」を参照してください。

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

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

グローバル・アプリケーション・コンテキストの所有権は、次のようになります。CREATE ANY CONTEXT権限とDROP ANY CONTEXT権限が付与されているユーザーは、グローバル・アプリケーション・コンテキストを作成および削除できますが、その所有権はSYSスキーマが所有します。コンテキストは、作成元のスキーマ・アカウントに関連付けられますが、このユーザーを削除した場合も、コンテキストは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を取得および設定します。

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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;
 /

この例の説明は、次のとおりです。

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

    usernameclient_idの値は設定されていません。したがって、NULLです。これらの設定によって、すべてのユーザー(データベース・ユーザー)が値にアクセスでき、この設定はサーバー全体に適用されます。

  • 13行目: SET_CONTEXTプロシージャで、namespaceglobal_hr_ctxに設定します。

  • 14行目: job_role属性を作成します。

  • 15行目: job_role属性の値をsec_levelに設定します。

  • 18–24行目: コンテキスト値を消去する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_idclient_identifier)の値をCookieに格納し、次のリクエストで戻されるように、エンド・ユーザーのHTMLページに送信する方法です。また、アプリケーションの参照表にクライアント識別子を保持し、他のユーザーのために使用されたり、エンド・ユーザーのセッション・タイムアウトを実装するために利用されるのを防止する必要があります。

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

  • namespace

  • attribute

  • value

  • username

  • client_id

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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;
 /

この例の説明は、次のとおりです。

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

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

  • 20–30行目: set_hr_ctxプロシージャを作成します。これは、グローバル・アプリケーション・コンテキストの属性を作成し、これらの属性に値を指定できるようにするプロシージャです。このプロシージャ内では、次の操作が実行されます。

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

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

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

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

  • 32–37行目: クライアント・セッション識別子を消去するclear_hr_sessionプロシージャを作成します。33行目では、正しいセッションID(つまり、5行目で定義したsession_id_p変数に格納されているID)を確実に消去するように、session_id_p変数を設定しています。

  • 39–44行目: 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を使用してください。

クライアント・セッション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値の取得

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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);

この例の説明は、次のとおりです。

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

  • 7–8行目: 文selcidを実行する準備を整えます。

  • 10–11行目: クライアント・セッションIDの出力変数clientidを定義します。

  • 13–14行目: selcid変数に格納されている文を実行します。

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

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

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

中間層アプリケーションのコードでは、クライアント・セッション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でログインします。

    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;
    

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

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

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

アプリケーション・サーバーAppSvrを考えてみます。このサーバーは、クライアントSCOTTにクライアント識別子12345を割り当てています。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が使用するブラウザに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によって設定されているグローバル・コンテキストにはアクセスできません。これは、APPSMGRでログインしたユーザーのみがこのコンテキストを参照できるように、AppSvrによって指定されているためです。AppSvrが次の文を使用した場合は、12345に設定されたクライアントIDを持つすべてのユーザー・セッションが、グローバル・コンテキストを参照できます。

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)に格納されます。

このタイプのアプリケーション・コンテキストの利点は、個々のアプリケーションが特定の非データベース・ユーザー・セッションをチェックできる点です。このタスクをデータベースで実行する必要はありません。他の利点は、アプリケーション・コンテキスト値を設定するためのコールが、サーバーに対する次のコールに含まれている点です。これによってパフォーマンスが向上します。

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

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

クライアント・セッション・ベースのアプリケーション・コンテキストを構成するには、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を指定します。

JDBCの場合は、次の書式のコマンドを使用します。

public void setApplicationContext(
  string CLIENTCONTEXT,
  string attribute,
  string value)
throws SQLException;

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

  • attribute: 値の設定が必要な属性を表します。

  • value: 属性に割り当てる値を表します。


関連項目:


OCIAppCtx関数の詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』のスケーラブル・プラットフォームの管理に関する項を参照してください。

クライアント・セッションIDの取得

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

SELECT SYS_CONTEXT('CLIENTCONTEXT', attribute) FROM dual;

SELECT VALUE FROM SESSION_CONTEXT WHERE NAMESPACE='CLIENTCONTEXT' AND 'attribute='CLIENT_IDENTIFIER' ;

attributeの値には、CLIENTCONTEXTネームスペースにすでに設定されているいずれかの属性を指定できます。設定されている属性のみが取得されます。それ以外の場合はNULLが戻ります。通常、属性はOCIAppCtxSetコールを使用して設定します。OCIコードにDBMS_SESSION.SET_CONTEXTコールを埋め込み、属性値を設定することもできます。

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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);

この例の説明は、次のとおりです。

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

  • 7–8行目: 文selcidを実行する準備を整えます。

  • 10–11行目: クライアント・セッションIDの出力変数clientidを定義します。

  • 13–14行目: selcid変数に格納されている文を実行します。

  • 16行目: 取得したクライアント・セッション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);

JDBCの場合は、次のコマンドを使用します。

public void setApplicationContext(String CLIENTCONTEXT,
                   string attribute,
                   string value)
                   throws SQLException;

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

  • attribute: 値の消去が必要な属性を表します。

  • value: 0または空の文字列("")を指定します。

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

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

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

JDBCの場合は、次の書式のコマンドを使用します。

public void clearAllApplicationContext(
                        String CLIENTCONTEXT)
                        throws SQLException;

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

表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

データベース内のすべての駆動コンテキストが表示されます。このビューの列は、ALL_POLICY_CONTEXTSの各列と同じです。

SESSION_CONTEXT

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

USER_POLICY_CONTEXTS

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

V$CONTEXT

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

V$SESSION

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



ヒント:


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