8 Oracle Fusion Middlewareのアプリケーション・セッション・サービス

Real Application Securityは、アプリケーション・セッションを透過的かつ安全に設定するためのアプリケーション・セッション・サービスをOracle Fusion Middlewareで提供し、既存のアプリケーション・ユーザー、ロール、セキュリティ・コンテキストをサポートします。このアプリケーション・セッション・サービスは、アプリケーション・セッションのセットアップおよびアプリケーションがアプリケーション・セッションで使用できる一連のAPIに使用されるサーブレット・フィルタです。このアプリケーション・セッション・サービスは、Oracle Fusion Middlewareによって外部で管理されるユーザーとロールをサポートします。

Oracle Database 12cリリース1 (12.1.0.2)以降、このアプリケーション・セッション・サービスはOracle Platform Security Service (OPSS)をアプリケーション・セキュリティ・プロバイダとして使用して、Java EE Webアプリケーションをサポートします。このアプリケーション・セッション・サービスは、OPSSでアプリケーションとともにサポートできるJava EEコンテナにデプロイできます。

Real Application Securityの概念について

Real Application SecurityはOracle Database認可システムとして、誰(アプリケーション・ユーザー)がどのデータベース・リソース(マイ・レポート、マイSSNの従業員の購買注文レコード)でどのアプリケーション・レベルの操作(ApprovePurchaseOrder、ViewSSN)を実行できるかを守らせることで、アプリケーションのセキュリティをサポートします。アプリケーション・セッションは、アプリケーション・セキュリティを徹底するために使用されます。一般に、ユーザーとロールは外部でプロビジョニングされます。つまり、エンタープライズ・ユーザーはアイデンティティ・ストアでプロビジョニングされ、アプリケーション・ロールはOracle Identity ManagementやOracle Entitlement Server (OES)などのポリシー・ストアで管理されます。

アプリケーション・ユーザーおよびロールを外部で管理

Real Application Securityは、アプリケーション・ユーザーおよびロールのプロビジョニングを管理するために、Oracle Entitlement Serverなどの外部パーティによってプロビジョニングされたユーザーとロールをサポートします。他方、OPSSはアプリケーション・ロールのセキュリティを徹底するための実行時セキュリティ・フレームワークを提供します。これらは外部アプリケーション・ユーザーおよび外部アプリケーション・ロールと呼ばれます(詳細は、Oracle Fusion MiddlewareとReal Application Securityの統合を参照)。

Real Application Securityには、データベースでネイティブに管理されるアプリケーションのユーザーおよびロールもあり、これらはReal Application Securityアプリケーション・ユーザーおよびアプリケーション・ロールと呼ばれます(詳細は、アプリケーション・ユーザーおよびアプリケーション・ロールの構成を参照)。

外部アプリケーション・ユーザーおよび外部アプリケーション・ロールについては、Real Application Securityはユーザーのロール割当てを含め、ユーザー・プロビジョニングを管理しません。ただし、データベース内のネイティブなアプリケーション・ユーザーおよびアプリケーション・ロールについては、アプリケーション・ユーザーへのアプリケーション・ロールの付与、アプリケーション・ロールへのデータベース・ロールの付与、アプリケーション・ロールへのアプリケーション・ロールの付与がデータベースで管理されます。Real Application Securityアプリケーション・ユーザーとアプリケーション・ロールおよび外部アプリケーション・ユーザーと外部アプリケーション・ロールの両方がアプリケーション・セッションでサポートされ、データ・セキュリティ・ポリシーで使用できます。アイデンティティ・ストアで外部から管理されるユーザーとデータベースでネイティブに管理されるユーザーの両方に、アプリケーション権限を付与できます。

Oracle Fusion Middlewareのアプリケーション・セッション

アプリケーション・セッションはアプリケーション・ユーザーの実行時セキュリティ・コンテキストを表します。これには、ユーザーID、データベースおよびアプリケーション・ロール、ネームスペース属性値が含まれます。Oracle Fusion Middlewareのアプリケーション・セッションは、外部で管理されるユーザーおよびロールを使用しています。アプリケーション・セッションの構成の詳細は、アプリケーション・ユーザー・セッションの構成を参照してください。

Oracle Fusion Middlewareのセッション・マネージャ

Real Application Securityでは、セッション・マネージャがアプリケーション・セッション操作を認可し、アプリケーション・セッションの作成および変更に必要な権限を持っています。アプリケーション・コードまたはアプリケーション・データベース接続は、これらの権限を持つことができません。データベースに対しては、セッション・マネージャはReal Application Security直接ログイン・ユーザーです(直接ログイン・アプリケーション・ユーザー・アカウントの作成を参照)。アプリケーション・セッション・サービスの初期化開始時にデータベースと通信し、認可資格証明に基づいてデータベース・サーバーと信頼関係を構築します。その後、このメカニズムを使用して、アプリケーションの代理でアプリケーション・セッションの操作を引き続き認可します。

Oracle Fusion Middlewareの動的ロール

アプリケーション・ロール以外に、アプリケーション・セッションでは動的ロールをサポートしています。これは、データベースでネイティブに定義する必要があるReal Application Securityロールです(動的アプリケーション・ロールを参照)。このロールは、ユーザーまたは他のロールには付与されません。実行時にアプリケーション・セッションでプログラムによって有効にする必要があります。これはReal Application Securityフィルタで自動的に行うか、信頼できるアプリケーション・コードによって明示的に行います。

動的ロールはリクエスト範囲またはセッション範囲として定義できます。セッション範囲では、次回の連結で無効化するように明示的に指定した場合を除き、有効化された動的ロールは次回の連結でも引き続き有効です。リクエスト範囲では、アプリケーション・セッションが接続から連結解除された後、ロールは無効化されます。

動的ロールには2つの一般的な用途があります。

  • オブジェクト権限

    アプリケーション・ユーザーはデータベース・ユーザーではありません。アプリケーション・ユーザーとアプリケーション・ロールが外部アイデンティティ・ストアでプロビジョニングされるときに、これらのオブジェクト権限をReal Application Security動的ロールに付与できます。Real Application Securityフィルタがアプリケーション・ユーザーにアプリケーション・セッションを設定する際、現在のアプリケーションにアクセスしている各アプリケーション・セッションで動的ロールを有効化します。動的ロールは、現在のアプリケーション専用です。

  • アプリケーション・セッション権限の昇格

    一部のデータベース操作を実行するために、特定の信頼できるアプリケーション・コードに、一時的に高い権限を付与する必要があります。これをサポートするには、Javaコード・ベース・ポリシーを使用して宣言された信頼できるコードから連結されるアプリケーション・セッション中に、Real Application Security動的ロールを有効にします。連結解除時には、ロールを無効にする必要があります。

    ユースケースの1つとして、セッション・ネームスペース属性がReal Application Securityで詳細にセキュリティ保護されている場合のアプリケーション・ネームスペースの設定があげられます。ネームスペースは、データベースでネームスペース・テンプレートとして事前定義しておく必要があります。定義時には、ネームスペースの関連ACLで認可ポリシー、つまり、誰(ユーザー/ロール)がネームスペースで何(modify_namespace、modify_attribute)を実行できるかを指定できます。信頼できるアプリケーション・コードのみがネームスペース属性を変更できるように、動的ロールに権限が付与されます。また、動的ロールは、Javaコード権限で識別される特定の信頼できるアプリケーション・コードによってプログラムを使用してのみ有効化できます。これにより、信頼できるコードのみが特定のネームスペースを設定できるユースケースがサポートされます。

Oracle Fusion Middlewareのアプリケーション・セッション・サービスについて

図8-1は、Oracle Fusion Middlewareに実装されたアプリケーション・セッション・サービスを示しています。

図8-1 Oracle Fusion Middlewareのアプリケーション・セッション・サービス

図8-1の説明が続きます
「図8-1 Oracle Fusion Middlewareのアプリケーション・セッション・サービス」の説明

アプリケーション・セッション・サービスはOracle Fusion Middlewareと統合されたソリューションで、Oracle Fusion Middlewareを活用してデータベースでアプリケーション・セッションを提供します。Oracle Fusion Middlewareでは:

  • アプリケーション・ユーザーは、コンテナによって認証されます。WLSでは一般に、オーセンティケータはSSOサーバーを使用してユーザーを認証します。

  • アプリケーション・ユーザーおよびグループは、アイデンティティ・ストアで管理されます。

  • OPSSは、コンテナのセキュリティ・コンテキストに基づいてアプリケーション・セキュリティ・コンテキストを設定するアプリケーション・セキュリティ・フレームワークです。OPSSを使用したアプリケーション・セキュリティの詳細は、Oracle Application Server Containers for J2EEセキュリティ・ガイドを参照してください。

Real Application Securityサーブレット・フィルタはアプリケーション・セッションを透過的に設定し、アプリケーション・セッションをOPSSサブジェクトと同期します。サーバー・フィルタ・コードは、アプリケーション・セッションで次の働きをする一連のAPIで構成されています。

Real Application Securityは:

  • アプリケーション・セッションで外部ユーザーと外部ロールをサポートするAPIを提供します

  • セッション・マネージャを使用してセッションを認可します

  • ネームスペースでファイングレイン・アクセス・コントロールをサポートします

アプリケーション・セッション・フィルタについて

Real Application Securityアプリケーション・セッション・フィルタは、javax.servlet.Filterインタフェースを実装する標準Java EEサーブレット・フィルタです。このフィルタの基本機能は、認証されたユーザーのセキュリティ・コンテキスト(OPSSサブジェクト)に応じてアプリケーション・セッションを透過的に設定することです。

このアプリケーション・セッション・フィルタを使用することで、アプリケーション・セッションをアプリケーション間で継続的に共有できます。リクエストごとに作成することはできませんが、ステートフル・コンテキストに関連付けて、ログアウトするまで同じユーザーに対して再使用する必要があります。Webアプリケーションの場合、httpセッションがこのようなコンテキストです。ログオンからログアウトまで同じユーザーの継続的なアクセスについて、複数のシングル・サインオン・アプリケーションまたはコンテナ間で、コンテナによって管理されます。

httpセッション・オブジェクトは、ServletFilterからは常にアクセスできますが、汎用アプリケーション・コードからはアクセスできないことがあります。

この項の内容は次のとおりです: アプリケーション・セッション・フィルタ操作について

アプリケーション・セッション・フィルタ操作について

アプリケーション・セッション・フィルタは、次の方法でアプリケーション・セッションを設定します。

  • ユーザーの初回アクセスで、アプリケーション・セッションを作成します。

    ユーザーがログインしている場合は、認証コンテキストのユーザーとしてアプリケーション・セッションを作成します(OPSSサブジェクト)。

    ユーザーがログインしていない場合は、匿名ユーザーとしてアプリケーション・セッションを作成します。

  • 同じアプリケーションへのユーザーの後続アクセスでは、既存のアプリケーション・セッション・インスタンスを再使用します。

  • 複数のアプリケーションが同じReal Application Securityデータベースにアクセスする際、複数のアプリケーション間で同じアプリケーション・セッションを共有します。

  • 各httpリクエストの開始時にアプリケーション・セッションを同期して、現在のアプリケーション・セッションのユーザーとロールが常に認証コンテキスト(OPSSサブジェクト)と同期され、各アプリケーション・セッションで構成済の動的ロールのみが有効化されるようにします。

    同期は、OPSSサブジェクトの値をサーバーにプッシュし、現在のアプリケーション・セッションについてサーバーで計算された値を取得することによって行われます。

アプリケーション・コードを実行する前にフィルタを起動すると、アプリケーション・セッションのユーザーとロールは固定されます。ユーザーとロールの同期を行うのは、アプリケーション・コードではなくフィルタです。

アプリケーション・コードは、ネームスペースの設定を行います。フィルタは、以前のネームスペースを戻すのに役立つだけです。ネームスペースの設定の詳細は、ネームスペースAPIについてを参照してください。

アプリケーション・セッションは、httpセッションIDに基づいてローカルでキャッシュされます。httpセッションは、コンテナによって管理されます。Real Application Securityには、コンテナのアプリケーション・セッション・イベントをリッスンするためのアプリケーション・セッション・リスナーがあります。コンテナでhttpセッションが無効化されると、アプリケーション・セッションはReal Application Securityリスナーによってローカル・キャッシュから削除されます。

デプロイメントについて

Real Application Securityアプリケーション・セッション・サービスは1つのjarファイル、xsee.jarで配布されます。xsee.jar jarファイルは共通ディレクトリにデプロイすることをお薦めします。Webアプリケーション(web-inf/lib内のWARファイル)と一緒にはデプロイしないでください。この方法により、jarファイルをアプリケーション・コードと分離し、いくつかの特別なコード・ベース権限をアプリケーション・コードには付与せずにxsee.jar jarファイルにのみ付与できます。

xsee.jar jarファイルがCSFストアからセッション・マネージャの資格証明を取得するには、コード・ベース権限CredentialAccessPermissionxsee.jar jarファイルに付与する必要があります。フィルタは内部的にReal Application Securityセッション・マネージャを使用して、セッション操作を認可します。

例8-1では、xsee.jar jarファイルをWLSのドメイン/libディレクトリにデプロイしています。javaポリシー・ファイル(system-jazn-data.xml)にはCredentialAccessPermission特権があり、セッション・マネージャのキー/マップはデフォルト値を使用していると想定しています。

デプロイ手順については、Oracle WebLogic Serverの理解の標準Java EEデプロイメントに関する項を参照してください。

テストまたは評価を行うためのアプリケーションを簡単にすばやくデプロイするには、自動デプロイメントを使用します。これは、すべて(クラス、web.xml)を1つのWARファイルにパッケージし、Weblogic autodeployディレクトリにコピーすることで、アプリケーション・セッション・サービスを簡単にデプロイする方法です。Oracle WebLogic Serverへのアプリケーションのデプロイの開発ドメインへのアプリケーションの自動デプロイに関する項を参照してください。

セッション・マネージャの資格証明を作成するには、手動構成の手順2を参照してください。

例8-1 xsee.jarファイルへのコード・ベース権限CredentialAccessPermissionの付与

<grant>
            <grantee>
                <codesource>
                    <url>file:${domain.home}/lib/xsee.jar</url>
                </codesource>
            </grantee>
            <permissions>
                <permission>
                    <class>oracle.security.jps.service.credstore.CredentialAccessPermission</class>
                    <name>context=SYSTEM,mapName=oracle.rdbms.ras, keyName=default</name>
                    <actions>read</actions>
                </permission>
            </permissions>
 </grant>

アプリケーション・セッション・フィルタのアプリケーション構成について

フィルタは、アプリケーションのweb.xml構成ファイルで、標準的な方法で構成されます。特定のURLにのみ適用するように構成できます。これにより、データベース・アクセスを必要としない特定ページに、不必要なアプリケーション・セッションが設定されるのを防ぎます。フィルタは、ユーザー認証が実行され、認証コンテキストが確立されているとみなします。OPSSでは、ユーザーのアプリケーション・コンテキストはOPSSフィルタで計算されるため、フィルタ・チェーンのアプリケーション・セッション・フィルタの前にOPSSフィルタをデプロイする必要があります。アプリケーション・セッション・フィルタは、次のweb.xmlパラメータを使用します。

  • application.datasource

    アプリケーションはこのapplication.datasourceパラメータを使用します。アプリケーション・セッション・フィルタは、初期化操作、アプリケーション・セッション設定操作およびネームスペース操作にこのパラメータを必要とします。

  • dynamic.roles

    使用されるReal Application Security動的ロールのリストは、カンマ(,)で区切られます。データベースでセッション範囲として動的ロールが作成されている必要があります。作成されていない場合、次の例外がスローされます: ORA-46055: 無効なロールが指定されました

    このロールは、現在のアプリケーションの各アプリケーション・セッションに対して有効化され、他のアプリケーションでは自動的に無効化されます。これらの動的ロールは、匿名セッションに対して有効化される点に注意してください。各アプリケーション・セッションに不要な場合、動的ロールに過大に権限を付与しないでください。通常、動的ロールに付与する必要があるのはオブジェクト権限のみです。

    Real Application Securityによって保護されない表については、アプリケーションはアクセスのために必要に応じてアプリケーション・ユーザーではなくデータベース接続プール・ユーザーを使用できます。その場合、連結アプリケーション・セッションAPIコールは不要であり、動的ロールにオブジェクト権限は付与されません。

  • session.manager.pwd.keyおよびsession.manager.pwd.map

    session.manager.pwd.keyパラメータとsession.manager.pwd.mapパラメータ(oracle.rdbms.rasとして固定)は資格証明ストア内の資格証明(ユーザーIDとパスワード)を指します。session.manager.pwd.keyパラメータは、セッション・マネージャの資格証明を取得するために使用されます。現在、OPSS CSF資格証明ストアは資格証明の格納に使用され、CSF APIは実行時に資格証明を取得するために使用されます。また、セッション・マネージャのユーザーIDとパスワードは両方ともストアから取得できます。

    session.manager.pwd.keyパラメータのデフォルト値はdefaultです。アプリケーションでデフォルトの資格証明が使用されている場合、このパラメータは省略できます。

    アプリケーションでデフォルトの資格証明ではなく特定のセッション・マネージャを使用する場合、アプリケーションの管理者は別のキー名で資格証明を作成し、このパラメータを使用して構成する必要があります。詳細は、Oracle Application Server Containers for J2EEセキュリティ・ガイドの「OPSSセキュリティ・ストアの構成」を参照してください。

  • session.manager.pool.minおよびsession.manager.pool.max

    セッション・マネージャの接続は、中間層でのデータ・セキュリティ・ポリシー(ACL)の問合せにも使用されます。この接続はプールとして管理されます。session.manager.pool.minパラメータはプールの最小サイズを決定します。このパラメータはオプションです。デフォルト値は1です。

    session.manager.pool.maxパラメータはプールの最大サイズを決定します。このパラメータはオプションです。デフォルト値は3です。

    権限チェックが不要な場合は、session.manager.pool.min値とsession.manager.pool.max値の両方に対して、プール・サイズを1に設定する必要があります。

例8-2は、サーブレット・フィルタ、そのパラメータ、リスナーを含むアプリケーション・セッション・フィルタのサンプル構成を示しています。デフォルト値のあるパラメータはすべて、この例では省略されています。

例8-2 アプリケーション・セッション・フィルタのサンプル構成

<filter>
        <filter-name>ApplicationSessionFilter</filter-name>
        <filter-class>oracle.security.xs.ee.session.ApplicationSessionFilter</filter-class>
        <init-param>
            <param-name>application.datasource</param-name>
            <param-value>jdbc/myDBDS</param-value>
        </init-param>
        <init-param>
            <param-name>dynamic.roles</param-name>
            <param-value>my_drole</param-value>
        </init-param>
</filter>
<listener>
    <description>RAS Session Listener</description>
    <listener-class>oracle.security.xs.ee.session.ApplicationSessionListener</listener-class>
</listener>

ドメイン構成: OPSSおよびOracle Fusion Middlewareで動作するアプリケーション・セッション・サービスの設定

この項では、アプリケーション・セッション・サービスを使用するアプリケーションに必要な前提条件と構成について説明します。

この項には次のトピックが含まれます:

前提条件

Real Application Securityを使用するには、アプリケーション・セッション・サービスとOPSSの両方をOracle Fusion MiddlewareのJava EEコンテナにデプロイして構成する必要があります。

WebLogic Serverの場合、前提条件は次のとおりです。

  • Oracle database 12c JDBCドライバに対して動作保証されたJRFベースのWLSドメイン(OPSSは組み込まれています)。必要とする機能に応じて、1つのドライバjarだけでなく多数のJDBC jarが必要になることがあります(UCP、I18N、SQLXMLなど)。

  • Oracle Database 12cリリース1 (12.1)以降

WebLogic Server 10.3.6および12.1.2 JRFリリース(Oracle Fusion Middlewareの一部)の場合、付属するJDBCドライバはOracle Database 12c互換ではありません。Oracle Database 12c JDBC jar (ojdbc6.jarまたはojdbc7.jarおよび必要な機能に応じたその他のjar)を取得し、これらのjarをWebLogic Serverのクラスパスの前に追加する必要があります。詳細な手順は、Oracle WebLogic Server JDBCデータ・ソースの管理のセクションBを参照してください。

JDBCドライバとデータベースのバージョンが一致しない場合、Real Application Securityフィルタの初期化はエラー・メッセージが表示されて失敗します。次に例を示します。

  • Oracle Database 11g JDBCドライバがOracle Database 12cで使用されている場合、サーバー・ログに次のエラー・メッセージが表示されます: メソッドが欠落しているためRASセッション・マネージャを初期化できません

  • Oracle Database 12c JDBCドライバがOracle Database 11gで使用されている場合、サーバー・ログに次のエラー・メッセージが表示されます: ORA-00439: 機能は使用できません: Fusionセキュリティ

手動構成

アプリケーションでアプリケーション・セッション・サービスを使用するには、次の手動構成手順に従います。手順は、WebLogic 10.3.6および12.1.2、JRFリリースの両方に使用できます。

  1. Real Application Security jarをインストールします。

    xsee.jarxs.jar (ORACLE_HOME/jlib/)を、アプリケーションで消費できる共通ディレクトリにコピーします。WebLogicの場合、推奨される場所はDOMAIN_HOME/libです。これにより、同じドメインにデプロイされた多くのアプリケーションでReal Application Security jarを共有できます。

  2. Real Application Securityセッション・マネージャの資格証明を作成します。

    アプリケーション・セッション・フィルタのアプリケーション構成についてで説明したように、セッション・マネージャの資格証明はOPSSの資格証明ストアで作成する必要があります。これは、OPSSスクリプトを使用して行うことができます。OPSSスクリプトの使用方法の詳細は、Oracle Application Server Containers for J2EEセキュリティ・カイドの「OPSSスクリプト」の項を参照してください。

    createCred(map='oracle.rdbms.ras', key='default', user='myUsr', password='myPassword')  
    

    セッション・マネージャの資格証明は、ドメインに構成されているデフォルトの資格証明ストアに格納されています。map名は、Real Application Securityアプリケーション・セッション・サービスに事前定義されているoracle.rdbms.rasにする必要があります。これは固定されており、変更できません。

  3. コード権限をReal Application Security jarファイルに付与します。

    「デプロイメントについて」で説明したように、CSF権限をxsee.jarファイルに付与する必要があります。これも、OPSSスクリプトを使用して行います。

    grantPermission(codeBaseURL='file:${domain.home}/lib/xsee.jar', permClass='oracle.security.jps.service.credstore.CredentialAccessPermission',  permTarget='context=SYSTEM,mapName=oracle.rdbms.ras,keyName=*', permActions='read')
    

    前述のkeyName (*)はすべてのキー用です。特定のアプリケーション向けに作成されている場合、デフォルト以外のキーには、これ以上権限は必要ありません。

  4. web.xmlを構成し、Real Application Security API (連結/連結解除)を呼び出して、アプリケーションをビルド/デプロイします。web.xmlがどのように構成されるかについては、例8-2を参照してください。

    これらは、標準のJava EE開発手順です。

    attachSessionPrivileged APIをアプリケーション・コードで呼び出す場合は、「権限昇格APIについて」で説明したとおりにSessionCodePermissionをアプリケーション・コードに付与する必要があります。これは、手順3と似ています。次はその例です。

    grantPermission(codeBaseURL='file:${domain.home}/servers/DefaultServer/tmp/_WL_user/MyWar/pi47ig/war/WEB-INF/lib/trusted.jar', permClass=' oracle.security.xs.ee.session.SessionCodePermission',  permTarget=' MY_NS_DROLE, permActions='attach')
    grantPermission(codeBaseURL='file:${domain.home}/lib/xsee.jar', permClass=' oracle.security.xs.ee.session.SessionCodePermission',  permTarget=' MY_NS_DROLE, permActions='attach')
    

    OPSSスクリプトには、WLS管理サーバーが実行されている必要があります。この手動アプローチでは、オンライン構成のみサポートされます。手順4は、常にアプリケーション管理者が行う必要がありますが、手順1から3は、自動構成についてで説明されているように自動化できます。

自動構成について

Oracle Fusion Middlewareでは、構成ユーティリティを使用してアプリケーション・グループに共通設定を構成できます。WebLogicの場合、これはドメイン構成ウィザードです。今後のWLSリリース(リリース12.1.3)では、この構成ウィザードによって手順1から3 (手動構成)を自動化できます。この自動アプローチには、オフライン構成をサポートできるという利点もあります(管理サーバーが実行されていない場合)。

構成ウィザードを起動すると(<ORACLE_HOME>/oracle_common/common/bin/config.sh)、次のユーザー・インタフェース(UI)が示され、Real Application Security構成情報の入力を求めるメッセージが表示されます。

  • 最初のUIでは、アプリケーション・セッション・サービスは、選択するOracle Fusion Middleware機能の1つとして表示されます。選択すると、その依存関係(OPSS、JRFの一部)も自動的に選択されます。

  • 2つめのUIでは、デフォルト・セッション・マネージャの資格証明を入力するよう求められます。

コード権限を付与するUIはありません。これは、事前定義されたxmlファイルをドメインのsystem-jazn-data.xmlファイルに結合することで、自動的に行われます。事前定義されたxmlファイルには、必要なすべてのReal Application Securityコード権限付与が含まれます。

管理者がアプリケーションに別のセッション・マネージャを使用することを決定した場合、管理者は手動による手順2を実行するか、UIから特別なキー名を追加する必要があります。同じキー名をアプリケーションのweb.xmlに渡す必要があります。この場合、マップ名(ストア名)は引き続きoracle.rdbms.rasに固定されているため、コード権限を付与する必要はありません。すべてのキーはすでに内部的に付与されているためです。

アプリケーション・セッションAPIについて

アプリケーション・セッションAPIは、クラスApplicationSessionServiceを介して静的メソッドとして公開されます。APIは、現在のサブジェクトに基づいて設定された現在のアプリケーション・セッションで動作します。各APIの内部では、IDアサーションが内部的に実行され、現在のアプリケーション・セッションがサブジェクトと一致することが確認されます。不一致が見つかった場合、ApplicationSesseionException例外がスローされます。サブジェクトとして呼び指すために、アプリケーション・セッションAPIのコール元コードは、常にSubject.doAsの内部で実行する必要があります。詳細は、JDKのSubject.doAsを参照してください。

アプリケーション・セッションAPIについて

アプリケーション・セッションへの連結について

現在のユーザーのアプリケーション・セッションを、特定のデータベース接続に連結します。

現在のユーザーのアプリケーション・セッションに連結するアプリケーション・コードには、コード・ベース権限は必要ありません。アプリケーション・セッションはそのままで動作し、連結によって追加の権限が昇格されることはありません。

構文

public static void attachSession(java.sql.Connection conn)
                          throws ApplicationSessionException

パラメータ

パラメータ 説明

conn

データベース・サーバー・ラウンドトリップのJDBC接続

例8-3および例8-6を参照してください。

アプリケーション・セッションからの連結解除

現在のユーザーのアプリケーション・セッションを、特定のデータベース接続から連結解除します。

アプリケーション・セッションを常にアプリケーション・コードの最終ブロックから連結解除することをお薦めします。そうしないと、連結された接続が正しいユーザーの下で実行されていないコードに付与されることがあります。使用後にアプリケーション・セッションを適切に連結解除することは、コール元の責任です。

連結解除がコールされずに、同じ接続で連結が再度コールされると、サーバーは前に連結されたアプリケーション・セッションからの連結解除を施行して、現在のアプリケーション・セッションに連結します。

構文

public static void detachSession(java.sql.Connection conn)
                          throws ApplicationSessionException

パラメータ

パラメータ 説明

conn

データベース・サーバー・ラウンドトリップのJDBC接続

例8-3に、連結および連結解除APIをデータベース問合せとともに使用するサンプル・コードを示します。コール元は、問合せニーズに基づいて、連結コールと連結解除コールの境界を決定する必要があります。

例8-3 アプリケーション・セッションAPI: AttachSessionとDetachSession

/**
  * Typical application code calling attach/detach for database query
  */
public void queryHR(Connection conn) {
      String query = " select emp.employee_id, emp.salary from hr.employees emp";
      Statement stmt = null;
      ResultSet rs = null;
      String id, salary;
      try {
        // attach connection to the current application session
        ApplicationSessionService.attachSession(conn);
        stmt = conn.createStatement();
        rs = stmt.executeQuery(query);      
        while (rs.next()) {
          id = rs.getString("employee_id");
          salary = rs.getString("salary");
        }
      } catch (ApplicationSessionException e) {
      } catch (SQLException e) {
      } finally {   
         // detach the current application session from the connection
         try { ApplicationSessionService.detachSession(conn); } catch (Exception e) {}
         if (stmt != null) try {stmt.close();} catch (SQLException e) {};
         if (rs != null) try { rs.close();} catch (SQLException e{};
      }  
    }
アプリケーション・セッションの破棄

データベースで現在のアプリケーション・セッションを破棄して、現在のスレッドの実行コンテキストから削除します。これは、ログアウト時にアプリケーションによって呼び出す必要があります。最初にフィルタによって設定された現在のアプリケーション・セッションを破棄します。

構文

public static void destroySession(java.sql.Connection conn)
                           throws ApplicationSessionException

パラメータ

パラメータ 説明

conn

データベース・サーバー・ラウンドトリップのJDBC接続

例8-4に、アプリケーション・セッション・サービスを破棄するサンプル・コードを示します。

例8-4 アプリケーション・セッションAPI: DestroySession

    void doLogout(HttpServletRequest request) {
 
        DataSource dataSource = null;
        Connection conn = null;
 
 
        try {
            InitialContext ic;
            try {
                ic = new InitialContext();
 
                dataSource = (DataSource)ic.lookup("jdbc/myDBDS");
 
                if (dataSource != null)
                    try {
                        conn = dataSource.getConnection();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
            } catch (NamingException e) {
                e.printStackTrace();
            }
            // invalidate Http session
            request.getSession().invalidate();
            // destroy XS session at DB
            ApplicationSessionService.destroySession(conn);
 
        } catch (ApplicationSessionException e) {
            e.printStackTrace();
        } finally {
 
            if (conn != null)
                try {
                    conn.close();
                } catch (SQLException e) {
                }
        }
 
    }

権限昇格APIについて

この項では、次のトピックについて説明します: アプリケーション・セッションでの動的ロールの有効化

アプリケーション・セッションでの動的ロールの有効化

現在のアプリケーション・セッションを特定のデータベース接続に連結し、連結したアプリケーション・セッションでReal Application Security動的ロールを有効化します。これにより、アプリケーション・ネームスペースの設定など一部のデータベース操作を実行するために、信頼できるアプリケーション・コードに一時的に高い権限を付与できます。

これは、特定の信頼できるアプリケーション・コードのアプリケーション・セッション権限を昇格するためです。Real Application Security動的ロールは、連結時に有効化されます。信頼できるコードは、javaコード権限によって識別されます。

構文

public static void attachSessionPrivileged(java.sql.Connection conn,
                                           java.lang.String role)
                                    throws ApplicationSessionException

パラメータ

パラメータ 説明

conn

データベース・サーバー・ラウンドトリップのJDBC接続

role

特定の動的ロール、リクエスト範囲である必要があります

特定の動的ロールはそれぞれ、例8-5 (jazn-data.xmlで付与された権限)に示すようにコード・ベース権限に関連付けられています。

例8-6を参照してください。

使用上の注意

javaセキュリティ・マネージャがオンであるかオフであるか、常にAPIで内部的に権限がチェックされます。コール元に権限がある場合(これは、特定のロールがポリシー・ファイルで定義されたロールとも一致することを意味します)、特定の動的ロールが連結時に有効化されます。権限がない場合、APIはAccessControlExceptionで失敗します。

コール元コード(caller.jarファイル)とアプリケーション・セッション・サービス・コード(xsee.jar)は両方とも、SessioncodePermission権限を持っている必要があります。caller.jarがコンテナによって直接呼び出される場合は、これで十分です。caller.jarが別のアプリケーション・コードによって呼び出される場合、アプリケーション・コードにこの権限が必要かどうかは、コール元が判断します。コール元でアプリケーションにこの権限が必要ない場合、コール元はAccessController.doPrivilegedでnull AccessControllerContextを指定したattachSessionPrivilegedを呼び出すことができます。詳細は、Java APIを参照してください。これを実行することで、caller.jarはアプリケーション・コードを全面的に信頼します。

動的ロールは、現在のアプリケーション・セッションではなく連結されたアプリケーション・セッションでのみ有効化されます。連結および連結解除の期間内で有効化されます。データベースでリクエスト範囲として動的ロールが定義されている必要があります。定義されていない場合、次の例外がスローされます: ORA-46055: 無効なロールが指定されました

例8-5 権限昇格API

<grant>
            <grantee>
                <codesource>
                    <url>file:${domain.home}/servers/DefaultServer/tmp/_WL_user/MyWar/pi47ig/war/WEB-INF/lib/trusted.jar' </url>
                </codesource>
            </grantee>
            <permissions>
                <permission>
                    <class>oracle.security.xs.ee.session.SessionCodePermission</class>
                    <name> MY_NS_DROLE</name>
                    <actions>attach </actions>
                </permission>
            </permissions>
        </grant>
        <grant>
            <grantee>
                <codesource>
                    <url>file:${domain.home}/lib/xsee.jar</url>
                </codesource>
            </grantee>
            <permissions>
                <permission>
                    <class>oracle.security.xs.ee.session.SessionCodePermission</class>
                    <name>MY_NS_DROLE</name>
                    <actions>attac </actions>
                </permission>
            </permissions>
        </grant>

ネームスペースAPIについて

ネームスペースの作成について

現在のアプリケーション・セッションでネームスペースを作成します。指定されたネームスペースがデータベースで事前定義されていて、アプリケーション・セッションでADMIN_ANY_NAMESPACE権限が有効化されている場合を除き、連結されたアプリケーション・セッションがMODIFY_NAMESPACE操作を実行することをネームスペースACLで許可する必要があります。

構文

public static void createNamespace(java.sql.Connection conn,
                                   java.lang.String name)
                            throws ApplicationSessionException

パラメータ

パラメータ 説明

conn

データベース・サーバー・ラウンドトリップのJDBC接続

name

特定のネームスペース名

例8-6を参照してください。

ネームスペースの削除について

現在のアプリケーション・セッションからネームスペースを削除します。指定されたネームスペースがデータベースで事前定義されていて、アプリケーション・セッションでADMIN_ANY_NAMESPACE権限が有効化されている場合を除き、連結されたアプリケーション・セッションがMODIFY_NAMESPACE操作を実行することをネームスペースACLで許可する必要があります。

構文

public static void deleteNamespace(java.sql.Connection conn,
                                   java.lang.String name)
                            throws NamespaceNotFoundException,
                                   ApplicationSessionException

パラメータ

パラメータ 説明

conn

データベース・サーバー・ラウンドトリップのJDBC接続

name

特定のネームスペース名。

例8-6を参照してください。

ネームスペース属性の設定について

属性値を現在のアプリケーション・セッションのネームスペースに設定します。指定されたネームスペースがデータベースで事前定義されていて、アプリケーション・セッションでADMIN_ANY_NAMESPACE権限が有効化されている場合を除き、連結されたアプリケーション・セッションがMODIFY_ATTRIBUTE操作を実行することをネームスペースACLで許可する必要があります。

ネームスペースに属性が存在しない場合、APIは特定の値で属性を作成します。存在する場合は、既存の値を特定の値に設定します。

構文

public static void setNamespaceAttribute(java.sql.Connection conn,
                                         java.lang.String name,
                                         java.lang.String attribute,
                                         java.lang.String value)
                                  throws NamespaceNotFoundException,
                                         ApplicationSessionException

パラメータ

パラメータ 説明

conn

データベース・サーバー・ラウンドトリップのJDBC接続

name

特定のネームスペース名

attribute

特定のネームスペース属性名

value

特定のネームスペース属性値

例8-6を参照してください。

ネームスペース属性の削除について

現在のアプリケーション・セッションでネームスペースから属性を削除します。指定されたネームスペースがデータベースで事前定義されていて、アプリケーション・セッションでADMIN_ANY_NAMESPACE権限が有効化されている場合を除き、連結されたアプリケーション・セッションがMODIFY_ATTRIBUTE操作を実行することをネームスペースACLで許可する必要があります。

構文

public static void deleteNamespaceAttribute(java.sql.Connection conn,
                                            java.lang.String name,
                                            java.lang.String attribute)
                                     throws NamespaceNotFoundException,
                                            ApplicationSessionException

パラメータ

パラメータ 説明

conn

データベース・サーバー・ラウンドトリップのJDBC接続

name

特定のネームスペース名

attribute

特定のネームスペース属性名

例8-6を参照してください。

ネームスペース属性の取得

現在のアプリケーション・セッションでネームスペースから属性を取得します。特定のネームスペースを作成する必要があります。データベース接続は不要で、この操作に対する権限はチェックされません。

ネームスペースを変更するAPI(getNamespaceAttribute以外)は、入力パラメータとしてデータベース接続を持ちます。これらのAPIは、JVMの現在のアプリケーション・セッションでネームスペースを更新し、変更内容をデータベース表にシリアライズします。接続は連結する必要があります。連結されたアプリケーション・セッションを使用して、サーバーがネームスペースの変更を認可できるかどうかを特定します。

特定の信頼できるアプリケーション・コードにのみ、ネームスペースの設定を許可します。接続は、ネームスペースで昇格権限(MODIFY_NAMESPACEMODIFY_ATTRIBUTE)を持つ動的ロールで連結できます。これは、attachSessionPrivileged APIを使用し、ネームスペース権限のみを動的ロールに付与することで実現できます。

構文

public static java.lang.String getNamespaceAttribute(java.lang.String name,
                                                     java.lang.String attribute)
                                              throws NamespaceNotFoundException,
                                                     ApplicationSessionException

パラメータ

パラメータ 説明

name

特定のネームスペース名

attribute

特定のネームスペース属性名

例8-6に、ネームスペースAPIを使用してネームスペースを設定し、アプリケーション・セッションの権限昇格APIを使用するサンプル・サーブレット・フィルタを示します。

アプリケーション・ネームスペースの使用方法について知っておくべき重要な点

次の使用情報で、アプリケーション・ネームスペースの使用方法について重要な点をまとめます。

  • Real Application Securityフィルタは、すべてのアプリケーション・ネームスペースを現在のアプリケーション・セッションにキャッシュします。

    • 初回アクセスの場合、データベースに新規アプリケーション・セッションを作成する必要があります。この時点で、まだアプリケーション・ネームスペースは設定されていません。

    • ユーザーの以後のアクセスでは、フィルタが常に、アプリケーション・セッションに作成されたすべてのネームスペースをJVMの現在のアプリケーション・セッションにキャッシュします。

  • アプリケーション・コードは常に、現在のアプリケーション・セッションからネームスペースをアクセスします。各更新操作は、表および現在のアプリケーション・セッション(JVM)の値を変更する、サーバーへのラウンド・トリップです。そのために、各更新APIにはデータベース接続パラメータがあります。ただし、読取り属性は、データベースにアクセスせずにJVMの現在のアプリケーション・セッションから読み取るローカル操作です。

  • ネームスペースの変更が正常に完了すると、変更内容は新たに連結されたアプリケーション・セッションだけでなく、すでに連結されたアプリケーション・セッションにも伝播されます。連結されたアプリケーション・セッションはすべて、単一ソース(現在のアプリケーション・セッション)を参照するためです。

  • 現在のアプリケーション・セッションのネームスペースは、Webアプリケーションのhttpリクエスト範囲内で同じです。他のアプリケーションはいつでもネームスペースを変更できます。変更は、Real Application Securityフィルタによって現在のhttpリクエストの開始時に1回だけ取得されます。同じhttpリクエスト内で行われた連結はすべて、現在のアプリケーション・セッションの同じネームスペースを参照します。

  • アプリケーション・コードは、ネームスペース値の変更を完全に制御します。現在のアプリケーション・セッションのネームスペースをいつでも読み取り、ネームスペースAPIをコールしてネームスペースを更新するかどうかを決定します。

例8-6 ネームスペースAPI

/**
  * Trusted application code (servlet filter) sets up namespace
  * Using privilege elevation and namespace APIs
  */
public void doFilter(ServletRequest request, ServletResponse response,  FilterChain chain) throws IOException, ServletException {
   Connection conn = null;
   try {
     conn = myDatasource.getConnection();
     // Attach an application session with a dynamic role.
     ApplicationSessionService.attachSessionPrivileged(conn, "myNSRole");
     try {
       // Get the current value.
       String currentValue = ApplicationSessionService.getNamespaceAttribute("mySecuredNS", "myAttribute");
       // If the current value is not desired, set it.
       if  ("myValue".compareToIgnoreCase(currentValue) != 0)
          ApplicationSessionService.setNamespaceAttribute(conn, "mySecuredNS", "myAttribute", "myValue");             
     } catch (NamespaceNotFoundException e) {
       // Namespace is not found, create it.
       ApplicationSessionService.createNamespace(conn, "mySecuredNS");
       // Set the attribute.
       ApplicationSessionService.setNamespaceAttribute(conn, "mySecuredNS", "myAttribute", "myValue");            
     }
   } catch (SQLException e) {
   } catch (ApplicationSessionException e) {
   } finally {
     // Detach an application session.
     try { ApplicationSessionService.detachSession(conn); } catch (Exception e) {}
     if (conn != null) try { conn.close();} catch (Exception e) {}
   }
    // Execution of application code.
    chain.doFilter(request, response);

権限チェックAPIについて

この項では、次のトピックについて説明します: ACLの権限のチェック

ACLの権限のチェック

指定された接続の連結されているアプリケーション・セッションを使用して、ACLの権限をチェックします。次の使用上の注意が伴います。

  • 連結された接続が指定されている必要があります。権限チェックは、連結されているアプリケーション・セッションに基づきます。attachSessionPrivilegedコールを介して、連結されているアプリケーション・セッションに、現在のアプリケーション・セッションより多くの権限を付与できます。

  • APIはACL IDの入力パラメータを取得します。これは、ORA_GET_ACLID演算子を使用して表から問い合せることができます。この演算子は、現在の行に関連付けられている一連のACL IDを返します。

  • このAPIは、権限名の入力パラメータを取得します。この入力パラメータは、SELECTまたはUPDATEなどのDML権限か、他のユーザー定義権限です。

構文

public static boolean checkPrivilege(java.sql.Connection conn,
                                     byte[] acls,
                                     java.lang.String privilege)
                              throws ApplicationSessionException

パラメータ

パラメータ 説明

conn

データベース・サーバー・ラウンドトリップのJDBC接続

acls

行形式での特定のACL ID

privilege

特定の権限名

例8-7では、行に関連付けられているACLを取得して、ACLのUPDATE権限をチェックします。

例8-7 権限チェックAPI

    public Collection<Employee> queryHR(Connection conn ) {
 
 
 
      Statement stmt = null;
      ResultSet rs = null;
 
      Collection<Employee> result = new ArrayList<Employee>();
 
      try {
        // attach session
        ApplicationSessionService.attachSession(conn);
 
        stmt = conn.createStatement();
        rs = stmt.executeQuery(query);
 
        while (rs.next()) {
          Employee emp = new Employee();
 
          emp.setId(rs.getString("EMPLOYEE_ID"));
 
          AuthorizationIndicator ai =
                    ((OracleResultSet)rs).getAuthorizationIndicator("salary");
 
          if (ai == AuthorizationIndicator.NONE) {
            emp.setSalary(rs.getString("salary"));
          } else {
            emp.setSalary("******")  ;
          }
 
 
          // get ACL associated with the row
          emp.setAcl(rs.getBytes("acl_id"));
          // check "update" privilege
          boolean canUpdate = ApplicationSessionService.checkPrivilege(conn, emp.getAcl(), "UPDATE");
 
 
          emp.setUpdate(canUpdate);
          result.add(emp);
 
 
          emp.setFname(rs.getString("first_name"));
          emp.setLname(rs.getString("last_name"));
          emp.setEmail(rs.getString("email"));
          emp.setPhone(rs.getString("phone_number"));
          emp.setManagerId(rs.getString("manager_id"));
          emp.setDepId(rs.getString("department_id"));
 
        }
      } catch (ApplicationSessionException e) {
          e.printStackTrace();
          // process me
      } catch (SQLException e) {
          // process me
          e.printStackTrace();
      } finally {
         if (stmt != null) try {stmt.close();} catch (SQLException e) {};
         if (rs != null) try { rs.close();} catch (SQLException e)  {};
         try {ApplicationSessionService.detachSession(conn);} catch (ApplicationSessionException e) {};
 
      }
 
      return result;
    }

人事管理デモのユースケース: Javaでの実装

この項では、アプリケーション・セッション・サービスで、Oracle Fusion Middlewareによって外部で管理されるユーザーとロールをサポートする方法を示します。このJava例は、セキュリティ人事管理(HR)シナリオに基づいています。サンプルHRスキーマのEMPLOYEES表を使用します。

関連項目:

ユーザーおよびグループからアプリケーション・ロールへのマッピングの詳細は、HRデモのユースケース - ユーザー・ロールについてを参照してください。

外部プリンシパル用のHRデモ・アプリケーションの設定(setup.sql)

例8-8に、外部プリンシパル用にHRデモ・アプリケーションを設定するセットアップ・スクリプト(setup.sql)を示します。

このセットアップ・スクリプトは、次の操作を実行します。

  • 外部ユーザーのオブジェクト権限のための動的ロールHROBJを作成します。

  • データ権限、更新、削除、挿入を示す、権限view_sensitive_infoと集約権限update_infoを含むセキュリティ・クラスHRPRIVSを作成します。これは事前定義クラスDMLから生じたクラスです。

  • EMP ACL、EMP_ACLを作成し、制限された部門の従業員レコードにアクセスするためのEMPHRMGRおよびHRREP権限を付与します。各外部プリンシパル(アプリケーション・ロール: HRREPHRMGRおよびEMP)は、OPSSポリシー・ストアGUID値と一致する必要があります。

  • セルフACL、SELF_ACLを作成して、従業員に自分のレコードを表示および更新するためのEMP権限を付与します。

  • マネージャACL、MGR_ACLを作成して、マネージャが自分の従業員の給与情報を確認できるようにします。

  • EMPLOYEES表に、データ・セキュリティ・ポリシーEMPLOYEE_DSを作成します。このポリシーは、部門60および100の従業員へのアクセスを制御するインスタンス・セットをEMP_ACLに定義します。機密性の高いSALARY列へのアクセスを制御する属性制約も定義します。

  • 2つの追加インスタンス・セットをSELF_ACLおよびMGR_ACLに定義し、データ・セキュリティ・ポリシーEMPLOYEE_DSに追加します。

  • ディスパッチャに、追加の権限をいくつか付与します。

例8-8 外部プリンシパル用のHRデモ・アプリケーションの設定

Rem Copyright (c) 2009, 2014, Oracle and/or its affiliates.
Rem All rights reserved.

SET ECHO ON
SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 100
 
-- A PL/SQL function to determine manager-report relationship
conn hr/hr;
 
create or replace package hrutil as
 function ismyreport(id IN PLS_INTEGER)
 return PLS_INTEGER ;
end hrutil;
/
 
create or replace package body hrutil as
 function ismyreport(id IN PLS_INTEGER)
   return PLS_INTEGER is
   mycount PLS_INTEGER ;
   myid    PLS_INTEGER ;
 begin
   select employee_id into myid from hr.employees
   where UPPER(email) = XS_SYS_CONTEXT('PROFILE_NS','EMAIL');
 
   select count(employee_id) into mycount from hr.employees
   where employee_id = id start with manager_id = myid
   connect by prior employee_id = manager_id ;
   return mycount ;
 end ismyreport ;
end hrutil ;
/
 
-- Create a dynamic role for object privileges for external users.
connect sys/password as sysdba
show con_name;
 
-- Create a dynamic role for HR object privileges.
exec xs_principal.delete_principal('HROBJ',XS_ADMIN_UTIL.CASCADE_OPTION);
exec xs_principal.create_dynamic_role('HROBJ');
 
-- Create a db role to have HR object privileges.
drop role hr_db_obj;
create role hr_db_obj;
-- Grant object privilege to the db role.
grant select, insert, update, delete on hr.employees to hr_db_obj;
 
-- Grant db role to dynamic role.
grant hr_db_obj to HROBJ;
 
 
-- Create a security class with privilege view_sensitive_info, and
-- aggregate privilege update_info that implies data privileges,
-- update, delete, insert, which come from pre-defined security class
-- DML.
DECLARE
  priv_list  XS$PRIVILEGE_LIST;
BEGIN
  priv_list :=XS$PRIVILEGE_LIST(
     XS$PRIVILEGE(name=>'VIEW_SENSITIVE_INFO'),
     XS$PRIVILEGE(name=>'UPDATE_INFO',
                  implied_priv_list=>XS$NAME_LIST
                    ('"UPDATE"', '"DELETE"', '"INSERT"')));
 
  xs_security_class.create_security_class(
     name=>'HRPRIVS',
     parent_list=>XS$NAME_LIST('DML'),
     priv_list=>priv_list);
END;
/
 
-- External Principal (app role) Used for data security:
-- Such a principal must match the OPSS policy store.
-- roleName="HRREP" guid="37ED0D108C2F11E2BF802D569259982"
-- roleName="HRMGR" guid="4077A2B08C2F11E2BF802D569259982"
-- roleName="EMP"   guid="F917C3608CF011E2BF802D569259982"
 
-- Create an EMP Acl to grant EMP, HRMGR and HRREP privileges to access an employee record in the restricted departments.
DECLARE
  ace_list XS$ACE_LIST;
BEGIN
  ace_list := XS$ACE_LIST(
      XS$ACE_TYPE(privilege_list=>XS$NAME_LIST('"SELECT"','VIEW_SENSITIVE_INFO'),
                  granted=>true,
                  principal_name=>'"37ED0D108C2F11E2BF802D569259982"', principal_type=>XS_ACL.PTYPE_EXTERNAL),
      XS$ACE_TYPE(privilege_list=>XS$NAME_LIST('UPDATE_INFO'),
                  granted=>true,
                  principal_name=>'"4077A2B08C2F11E2BF802D569259982"', principal_type=>XS_ACL.PTYPE_EXTERNAL),
      XS$ACE_TYPE(privilege_list=>XS$NAME_LIST('"SELECT"'),
                  granted=>true,
                  principal_name=>'"F917C3608CF011E2BF802D569259982"', principal_type=>XS_ACL.PTYPE_EXTERNAL));
 
  xs_acl.create_acl(name=> 'EMP_ACL',
                   ace_list=> ace_list,
                   sec_class=>'HRPRIVS',
                   description=> 'Employee access to his/her data');
END;
/
 
-- Create a self Acl to grant EMP privileges to for an employee to see and update his own record.
-- Grant UPDATE, VIEW_SENSITIVE_INFO privileges to the EMP role.
DECLARE
 ace_list XS$ACE_LIST;
BEGIN
 ace_list := XS$ACE_LIST(
   XS$ACE_TYPE(privilege_list=> XS$NAME_LIST('"UPDATE"', 'VIEW_SENSITIVE_INFO'),
               principal_name=>'"F917C3608CF011E2BF802D569259982"', principal_type=>XS_ACL.PTYPE_EXTERNAL));
 
 xs_acl.create_acl(name=> 'SELF_ACL',
                   ace_list=> ace_list,
                   sec_class=>'HRPRIVS',
                   description=> 'Employee access to his/her data');
END;
/
 
--   Create Manager ACL, to allow a manager to see his employee's salary.
--   Grant VIEW_SENSITIVE_INFO privileges to EMP role on the Manager's employees.
--
DECLARE
 ace_list XS$ACE_LIST;
BEGIN
 ace_list := XS$ACE_LIST(
   XS$ACE_TYPE(privilege_list=> XS$NAME_LIST('VIEW_SENSITIVE_INFO'),
               principal_name=>'"F917C3608CF011E2BF802D569259982"', principal_type=>XS_ACL.PTYPE_EXTERNAL));
 
 xs_acl.create_acl(name=> 'MGR_ACL',
                   ace_list=> ace_list,
                   sec_class=>'HRPRIVS',
                   description=> 'Manager can see his reports salaray');
END;
/
 
-- Create data security policy for the EMPLOYEE table. The policy defines
-- an instant set to control the access to the employees in department
-- 60 and 100. It also defines an attribute constraint to control
-- the access to sensitive column SALARY.
DECLARE
  inst_sets XS$REALM_CONSTRAINT_LIST;
  attr_secs XS$COLUMN_CONSTRAINT_LIST;
BEGIN
  inst_sets :=
    XS$REALM_CONSTRAINT_LIST(
      XS$REALM_CONSTRAINT_TYPE(realm=> 'DEPARTMENT_ID in (60, 100)',
                           acl_list=> XS$NAME_LIST('EMP_ACL')));
 
  attr_secs :=
    XS$COLUMN_CONSTRAINT_LIST(
      XS$COLUMN_CONSTRAINT_TYPE(column_list=> XS$LIST('SALARY'),
                            privilege=> 'VIEW_SENSITIVE_INFO'));
 
  xs_data_security.create_policy(
          name=>'EMPLOYEES_DS',
          realm_constraint_list=>inst_sets,
          column_constraint_list=>attr_secs);
END;
/
 
-- Add more instance sets to the above data security.
declare
  inst1 xs$REALM_CONSTRAINT_TYPE;
  inst2 xs$REALM_CONSTRAINT_TYPE;
begin
 
  inst1 := xs$REALM_CONSTRAINT_TYPE(realm=> 'UPPER(email) = XS_SYS_CONTEXT(''PROFILE_NS'',''EMAIL'')',
                                acl_list=> XS$NAME_LIST('SELF_ACL'));
 
  xs_data_security.append_realm_constraints('EMPLOYEES_DS', inst1);
 
 
  inst2 := xs$REALM_CONSTRAINT_TYPE(realm=> 'hr.hrutil.ismyreport(employee_id) = 1',
                                acl_list=> XS$NAME_LIST('MGR_ACL'));
 
  xs_data_security.append_realm_constraints('EMPLOYEES_DS', inst2);
end;
/
 
-- Apply the data security policy on the table.
 
begin
  XS_DATA_SECURITY.apply_object_policy(schema=>'HR', object=>'EMPLOYEES',
                                       policy=>'EMPLOYEES_DS');
end;
/
 
-- Grant more privileges for the dispatcher.
exec XS_ADMIN_UTIL.GRANT_SYSTEM_PRIVILEGE('ADMIN_ANY_NAMESPACE','ts',XS_ADMIN_UTIL.PTYPE_XS);
grant select on  sys.dba_xs_session_roles to ts_role;
 
EXIT;

アプリケーション・セッション・フィルタ構成ファイル(web.xml)について

例8-9に、フィルタ、そのパラメータ、リスナを含む完全なアプリケーション・セッション・フィルタのサンプル構成ファイル(web.xml)を示します。例8-11に示すネームスペース(MyFilter.java)を設定するためのフィルタ、例8-10に示すMyHR.javaという名前のサンプル・サーブレット・アプリケーション、およびMySession.javaMyUpdate.javaおよびLogoutServlet.java(これは示されていません)を参照します。

MySessionV$XS_SESSION_ROLESビューを問い合せてアプリケーション・セッションのロールを表示し、XS$SESSIONネームスペースのユーザーを問い合せてアプリケーション・セッションのユーザーを表示し、V$XS_SESSION_NS_ATTRIBUTESビューを問い合せてアプリケーション・セッションのネームスペースを表示して、アプリケーション・セッションに連結します。

MyUpdateHR.EMPLOYEES表で更新を実行して、従業員の電話番号を更新します。

LogoutServletはログアウト操作を実行してから、データベースでアプリケーション・セッションを破棄します。

ApplicationSessionFilterフィルタ構成では、フィルタ・セクションはクラスApllicationSessionFilterを参照し、パラメータapplication.datasourceとパラメータ値jdbc/myDBDSを記述し、パラメータdynamic roles例8-8のセットアップ・スクリプトで作成された値HROBJを記述します。

例8-9 完全なアプリケーション・セッション・フィルタのサンプル構成

<?xml version = '1.0' encoding = 'UTF-8'?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
    <filter>
        <filter-name>JpsFilter</filter-name>
        <filter-class>oracle.security.jps.ee.http.JpsFilter</filter-class>
        <init-param>
            <param-name>enable.anonymous</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>remove.anonymous.role</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>application.name</param-name>
            <param-value>MyHRApp</param-value>
        </init-param>
        <!-- Following needed for Menu Security -->
        <!--init-param>
            <param-name>oracle.security.jps.jaas.mode</param-name>
            <param-value>subjectOnly</param-value>
        </init-param-->
    </filter>
    <filter>
        <filter-name>ApplicationSessionFilter</filter-name>
        <filter-class>oracle.security.xs.ee.session.ApplicationSessionFilter</filter-class>
 
        <init-param>
            <param-name>application.datasource</param-name>
            <param-value>jdbc/myDBDS</param-value>
        </init-param>
        <init-param>
            <param-name>dynamic.roles</param-name>
            <param-value>HROBJ</param-value>
        </init-param>
        <!--
         <init-param>
            <param-name>dispatcher.pool.max</param-name>
            <param-value>90</param-value>
        </init-param>
        -->
        <!-- init-param>
            <param-name>application.id</param-name>
            <param-value>MyHRApp</param-value>
        </init-param>
        <init-param>
            <param-name>session.provider</param-name>
            <param-value>XS</param-value>
        </init-param>
        <init-param>
            <param-name>db.url</param-name>
            <param-value>jdbc:oracle:thin:@myhost:1521:orcl</param-value>
        </init-param>
 
        <init-param>
            <param-name>dispatcher.id</param-name>
            <param-value>ts</param-value>
        </init-param>
 
        <init-param>
            <param-name>dispatcher.pwd.map</param-name>
            <param-value>XS_MAP</param-value>
        </init-param>
        <init-param>
            <param-name>dispatcher.pwd.key</param-name>
            <param-value>XS_KEY</param-value>
        </init-param>
        <init-param>
            <param-name>dispatcher.pool.min</param-name>
            <param-value>3</param-value>
        </init-param>
        <init-param>
            <param-name>dispatcher.pool.max</param-name>
            <param-value>10</param-value>
        </init-param -->
 
        <!--init-param>
            <param-name>namespaces</param-name>
            <param-value>sec_ns</param-value>
        </init-param-->
    </filter>
    <filter>
        <filter-name>MyFilter</filter-name>
        <filter-class>trusted.MyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>JpsFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>
    <filter-mapping>
        <filter-name>ApplicationSessionFilter</filter-name>
        <url-pattern>/myhr</url-pattern>
        <url-pattern>/mysession</url-pattern>
        <url-pattern>/myupdate</url-pattern>
        <url-pattern>/logout</url-pattern>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>
    <filter-mapping>
        <filter-name>MyFilter</filter-name>
        <url-pattern>/myhr</url-pattern>
        <url-pattern>/mysession</url-pattern>
        <url-pattern>/myupdate</url-pattern>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>
    <listener>
        <listener-class>oracle.security.xs.ee.session.ApplicationSessionListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>MySession</servlet-name>
        <servlet-class>app.MySession</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>LogoutServlet</servlet-name>
        <servlet-class>app.MyLogout</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>MyHR</servlet-name>
        <servlet-class>app.MyHR</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>MyUpdate</servlet-name>
        <servlet-class>app.MyUpdate</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>MySession</servlet-name>
        <url-pattern>/mysession</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>LogoutServlet</servlet-name>
        <url-pattern>/logout</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>MyHR</servlet-name>
        <url-pattern>/myhr</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>MyUpdate</servlet-name>
        <url-pattern>/myupdate</url-pattern>
    </servlet-mapping>
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>my servlet</web-resource-name>
            <url-pattern>/myhr</url-pattern>
            <url-pattern>/mysession</url-pattern>
            <url-pattern>/myupdate</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>valid-users</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>CLIENT-CERT,FORM</auth-method>
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
            <form-error-page>/error.jsp</form-error-page>
        </form-login-config>
    </login-config>
    <security-role>
        <role-name>valid-users</role-name>
    </security-role>
</web-app>

サンプル・サーブレット・アプリケーション(MyHR.java)について

例8-10に、例8-9に示すアプリケーション・セッション・フィルタのサンプル構成(web.xmlファイル)で参照されている、MyHR.javaというサンプル・サーブレット・アプリケーションを示します。

MyHRアプリケーションはEMPLOYEES表で問合せを実行して、結果を返します。権限がある場合は、ログイン資格証明に応じて、次に説明されている特定タスクを実行できます。

ACLの権限チェック(checkPrivilege)から、UPDATE権限がある場合はその従業員のレコードの更新を実行する権限があり、EMPLOYEE_IDにその従業員のレコードにアクセスできるリンクが表示されます。

例8-10 サンプル・サーブレット・アプリケーション(MyHR.java)

/* Copyright (c) 2009, 2014, Oracle and/or its affiliates.
All rights reserved.*/
 
package app;
 
import java.io.IOException;
import java.io.PrintWriter;
 
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
import java.util.ArrayList;
import java.util.Collection;
 
import javax.naming.InitialContext;
import javax.naming.NamingException;
 
import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import javax.sql.DataSource;
 
import oracle.jdbc.OracleResultSet;
import oracle.jdbc.OracleResultSet.AuthorizationIndicator;
import oracle.security.xs.ee.session.ApplicationSessionException;
import oracle.security.xs.ee.session.ApplicationSessionService;
 
public class MyHR extends HttpServlet {
    private static final String CONTENT_TYPE = "text/html; charset=UTF-8";
 
    String query = " select emp.EMPLOYEE_ID, emp.first_name, emp.last_name, " +
                   "        emp.email, emp.phone_number, salary, emp.manager_id, " +
                   "        emp.department_id,ora_get_aclids(emp) as acl_id" +
                   " from hr.employees emp";
 
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }
 
    public void queryHR(PrintWriter out) throws ApplicationSessionException {
 
        DataSource dataSource = null;
        Connection conn = null;
 
        try {
            InitialContext ic;
            try {
                ic = new InitialContext();
 
                dataSource = (DataSource)ic.lookup("jdbc/myDBDS");
 
                if (dataSource != null)
                    try {
                        conn = dataSource.getConnection();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
            } catch (NamingException e) {
                e.printStackTrace();
            }
 
            try {
                queryHR(conn, out);
            } catch (Exception e) {
                e.printStackTrace();
            }
 
        } finally {
 
            if (conn != null)
                try {
                    conn.close();
                } catch (SQLException e) {
                }
        }
 
    }
 
    public void doGet(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException,
                                                           IOException {
        response.setContentType(CONTENT_TYPE);
        PrintWriter pw = response.getWriter();
 
        pw.println(HEADER);
 
        pw.println("<h1><font size=\"+2\">RAS Session Service Demo</font></h1>");
        pw.println("<font size=\"+1\">");
        pw.println("You are logged in as <b>" + request.getRemoteUser() + "</b>");
 
        try {
            queryHR(pw);
        } catch (ApplicationSessionException e) {
            e.printStackTrace();
        }
 
        pw.println(FOOTER);
        pw.close();
    }
 
 
    public Collection<Employee> queryHR(Connection conn ) {
 
      Statement stmt = null;
      ResultSet rs = null;
 
      Collection<Employee> result = new ArrayList<Employee>();
 
      try {
        // attach session
        ApplicationSessionService.attachSession(conn);
 
        stmt = conn.createStatement();
        rs = stmt.executeQuery(query);
 
        while (rs.next()) {
          Employee emp = new Employee();
 
          emp.setId(rs.getString("EMPLOYEE_ID"));
 
          AuthorizationIndicator ai =
                    ((OracleResultSet)rs).getAuthorizationIndicator("salary");
 
          if (ai == AuthorizationIndicator.NONE) {
            emp.setSalary(rs.getString("salary"));
          } else {
            emp.setSalary("******")  ;
          }
 
          // get ACL associated with the row
          emp.setAcl(rs.getBytes("acl_id"));
          // check "update" privilege
          boolean canUpdate = ApplicationSessionService.checkPrivilege(conn, emp.getAcl(), "UPDATE");
 
          emp.setUpdate(canUpdate);
          result.add(emp);
 
          emp.setFname(rs.getString("first_name"));
          emp.setLname(rs.getString("last_name"));
          emp.setEmail(rs.getString("email"));
          emp.setPhone(rs.getString("phone_number"));
          emp.setManagerId(rs.getString("manager_id"));
          emp.setDepId(rs.getString("department_id"));
 
        }
      } catch (ApplicationSessionException e) {
          e.printStackTrace();
          // process me
      } catch (SQLException e) {
          // process me
          e.printStackTrace();
      } finally {
         if (stmt != null) try {stmt.close();} catch (SQLException e) {};
         if (rs != null) try { rs.close();} catch (SQLException e)  {};
         try {ApplicationSessionService.detachSession(conn);} catch (ApplicationSessionException e) {};
 
      }
 
      return result;
    }
 
    public void queryHR(Connection conn, PrintWriter out ) {
 
        Collection<Employee> list = queryHR(conn);
 
        PrintWriter pw = out;
 
        pw.println("<br>Displaying employee record(s) that you can access.<br>");
        pw.println("</font>");
        pw.println("<i>NOTE: Salary is only shown if you are authorized to view,
 and ID is shown as a link if you are authorized to perform an update.</i><br>");
 
        out.println("<table border=\"1\">");
 
        String tmp;
 
        if (list.size() > 0) {
            out.println("<tr>");
            out.println("<th>ID</th>");
            out.println("<th>First Name</th>");
            out.println("<th>Last Name</th>");
            out.println("<th>Email</th>");
            out.println("<th>Phone</th>");
            out.println("<th>Salary</th>");
 
            out.println("<th>Department ID</th>");
            out.println("<th>Manager ID</th>");
            out.println("</tr>");
        }
 
        for (Employee e: list)  {
 
            if (e.canUpdate()) {
                tmp = "<a href=\"update.jsp?id=" + e.getId() + "\">" + e.getId() + "</a>";
            } else {
                tmp = e.getId();
            }
 
            out.println("<tr><td>" + tmp + "</td>");
            out.println("<td>" +  e.getFname() + "</td>");
            out.println("<td>" +  e.getLname() + "</td>");
            out.println("<td>" +  e.getEmail() + "</td>");
            out.println("<td>" +  e.getPhone() + "</td>");
            out.println("<td>" +  e.getSalary() + "</td>");
            out.println("<td>" +  e.getDepId() + "</td>");
            out.println("<td>" +  e.getManagerId() + "</td></tr>");
 
        }
 
        out.println("</TABLE>");
 
    };
 
    class Employee {
 
        String id;
        String salary;
        boolean update;
        String fname;
        String lname;
        String email;
        String phone;
        String managerId;
        String depId;
        byte[] acl;
 
        public void setId(String id) {
            this.id = id;
        }
 
        public String getId() {
            return id;
        }
 
        public void setSalary(String salary) {
            this.salary = salary;
        }
 
        public String getSalary() {
            return salary;
        }
 
        public void setUpdate(boolean canUpdate) {
            this.update = canUpdate;
        }
 
        public boolean canUpdate() {
            return update;
        }
 
        public void setFname(String fname) {
            this.fname = fname;
        }
 
        public String getFname() {
            return fname;
        }
 
        public void setLname(String lname) {
            this.lname = lname;
        }
 
        public String getLname() {
            return lname;
        }
 
        public void setEmail(String email) {
            this.email = email;
        }
 
        public String getEmail() {
            return email;
        }
 
        public void setPhone(String phone) {
            this.phone = phone;
        }
 
        public String getPhone() {
            return phone;
        }
 
        public void setManagerId(String managerId) {
            this.managerId = managerId;
        }
 
        public String getManagerId() {
            return managerId;
        }
 
        public void setDepId(String depId) {
            this.depId = depId;
        }
 
        public String getDepId() {
            return depId;
        }
 
        public void setAcl(byte[] acl) {
            this.acl = acl;
        }
 
        public byte[] getAcl() {
            return acl;
        }
    }
 
    private static String HEADER = "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>"
            + "<meta content=\"text/html; charset=UTF-8\" http-equiv=\"content-type\"/>"
            + "<title>Oracle</title>"
            + "<link href=\"css/general.css\" type=\"text/css\" rel=\"stylesheet\"/>"
            + "<link href=\"css/window.css\" type=\"text/css\" rel=\"stylesheet\"/>"
            + "<link href=\"css/login.css\" type=\"text/css\" rel=\"stylesheet\"/>"
            + "<script type=\"text/javascript\">"
            + "  if (top != self) top.location.href = location.href;"
            + "</script>"
            + "<style type=\"text/css\">"
            + "html { background-color: #001C34;}"
            + "</style>"
            + "</head>"
            + "<body onload=\"document.loginData.j_username.focus();\">"
            + "  <div id=\"top\">"
            + "   <div id=\"login-header\">"
            + "    <div id=\"login-logo\">"
            + "    <img  src=\"images/logo.png\"/>"
            + "</div>"
            + "  </div>"
            + "  <div id=\"content\">"
            + "<div id=\"app_data\"><div id=\"title\"></div>";
 
        private static String FOOTER = "<a href=\"/myapp/logout\">Logout</a>"
                + "</div></div><div id=\"info\"></div></div></body></html>";
}

アプリケーション・ネームスペースを設定するためのフィルタ(MyFilter.java)について

例8-11に、アプリケーション・ネームスペースを設定するためのフィルタを示します。このフィルタはMyHR.javaという名前で、例8-9に示すアプリケーション・セッション・フィルタのサンプル構成(web.xmlファイル)で参照されています。

このフィルタは別個のjarとしてデプロイする必要があり、jarファイルにSessionCodePermissionを付与する必要があります。

このフィルタはまずV$XS_SESSION_ROLESビューを問い合せて、Real Security Applicationセッションのロールを表示します。次に、このフィルタは信頼できるアプリケーション・コード(フィルタ)がネームスペース(getNamespaceAttribute)が存在するかどうかを最初にチェックする方法をデモし、存在しない場合は、セッション権限昇格(attachSessionPrivileged)を使用してセキュリティ・クリティカルなネームスペースおよびネームスペースAPI (createNamespacesetNamespaceAttribute)を設定してネームスペースを作成し、ネームスペース属性を設定します。

例8-11 アプリケーション・ネームスペースを設定するためのフィルタ

/* Copyright (c) 2009, 2014, Oracle and/or its affiliates.
All rights reserved.*/

package trusted;
 
 
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.InitialContext;
import javax.naming.NamingException;
 
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import oracle.security.xs.ee.session.ApplicationSessionException;
import oracle.security.xs.ee.session.ApplicationSessionService;
import oracle.security.xs.ee.session.NamespaceNotFoundException;
 
 
/**
 * Demonstrate how trusted application code (a filter) can set up
 * security critical namespace using session privilege elevation and
 * namespace APIs.
 *
 * The filter should be deployed as a separate jar, and SessionCodePermission
 * should be granted to the jar.
 */
 
public class MyFilter implements Filter {
    private FilterConfig _filterConfig = null;
    DataSource myDatasource = null;
 
    public void init(FilterConfig filterConfig) throws ServletException {
        _filterConfig = filterConfig;
 
    }
 
    public void destroy() {
        _filterConfig = null;
    }
 
 
    public void querySessionRoles(Connection conn) throws SQLException {
 
        String query =
            "select role_name from v$xs_session_roles order by role_name";
        String roles = null;
 
        try {
 
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery(query);
 
            System.out.println("<p> roles in RAS session (from myfilter):</p>");
 
            System.out.println("<TABLE>");
 
            while (rs.next()) {
 
                roles = rs.getString(1);
                System.out.println("<tr><td>" + roles + "</td></tr>");
            }
            System.out.println("</TABLE>");
        } finally {
 
        }
 
        return;
    }
 
 
    private boolean namespaceExists(String ns, String attribute, String value) throws ApplicationSessionException {
 
 
        try {
            return value.equalsIgnoreCase(ApplicationSessionService.getNamespaceAttribute(ns, attribute));
        } catch (NamespaceNotFoundException e) {
            return false;
        }
    }
 
    private Connection getConnection() {
 
        DataSource dataSource = null;
        InitialContext ic;
        try {
            ic = new InitialContext(); //TODO cache context
 
            dataSource = (DataSource)ic.lookup("jdbc/myDBDS");
 
            if (dataSource != null)
                try {
                    return dataSource.getConnection();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        } catch (NamingException e) {
            e.printStackTrace();
        }
        return null;
    }
 
 
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) {
 
        Connection conn = null;
 
        try {
 
            String email = ((HttpServletRequest)request).getRemoteUser();
            if ( email != null && !namespaceExists("PROFILE_NS", "EMAIL", email )) {
 
 
 
                conn = getConnection();
 
                //AccessController.doPrivileged(new AttachAction(conn), null);
                ApplicationSessionService.attachSessionPrivileged(conn, "SESSION_NS_DROLE");
 
 
 
                ApplicationSessionService.createNamespace(conn, "PROFILE_NS");
                ApplicationSessionService.setNamespaceAttribute(conn, "PROFILE_NS", "EMAIL", email);
 
                ApplicationSessionService.detachSession(conn);
            }
 
        } catch (ApplicationSessionException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
 
            if (conn != null)
                try {
                    conn.close();
                } catch (SQLException e) {
                }
            }
 
        try {
            chain.doFilter(request, response);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ServletException e) {
            e.printStackTrace();
        }
    }
}

HRデモのユースケース - ユーザー・ロールについて

HRデモのユースケースでは、アイデンティティ管理ストアにユーザー名、ユーザー名のパスワード、グループ名が含まれます。他方、OPSSセキュリティ・ストアにはアプリケーション・ロールとユーザーおよびグループからアプリケーション・ロールへのマッピングが含まれます。例8-12に、あるユーザーLPOPPについて、ユーザーおよびグループからアプリケーション・ロールへのマッピングを行うためのコード・スニペットを示します。

例8-12 ユーザーおよびグループからアプリケーション・ロールへのマッピング

<app-role>   
<name>EMP</name>
<display-name>Employee for dept #60 and dept #100</display-name>
<description>HR manager for dept #60 and representative for dept #100</description>
<guid>F917C3608CF011E2BF802D569259982</guid>
<class>oracle.security.jps.service.policystore.ApplicationRole</class>
<members>
    <member>
        <class>weblogic.security.principal.WLSUserImpl</class>
        <name>LPOPP</name>
    </member>
</members>
</app-role>

HRデモ(1) - 従業員LPOPPとしてログインについて

表8-1に、従業員LPOPPとしてログインした場合にアクセスできる従業員レコードを示します。全員の給与情報以外のレコードおよび自分の給与情報を表示でき、自分の連絡先情報を更新できます。

このアクセス権は、次によって設定されます。

  • レルムおよび権限付与(1): DEPARTMENT_ID in (60, 100)およびSELECT to EMP

  • レルムおよび権限付与(2): UPPER(email) = XS_SYS_CONTEXT("PROFILE_NS","EMAIL")およびUPDATE, VIEW_SENSITIVE_INFO to EMP

  • 列制約: SALARYにはVIEW_SENSITIVE_INFO権限が必要です

給与は、ユーザーに表示権限がある場合にのみ表示され、更新権限がある場合はリンクとしてIDが示されます(表にイタリック形式で)。

例8-1 セッション・サービスHRデモ(1) - 従業員LPOPPとしてログイン

ID 電子メール 電話番号 給与 部門ID マネージャID

103

Alexander

Hunold

AHUNOLD

510.222.3388

******

60

102

104

Bruce

Ernst

BERNST

590.423.4568

******

60

103

105

David

Austin

DAUSTIN

590.423.4569

******

60

103

106

Valli

Pataballa

VPATABAL

590.423.4560

******

60

103

107

Diana

Lorentz

DLORENTZ

590.423.4567

******

60

103

108

Nancy

Greenberg

NGREENBE

515.124.4569

******

100

101

109

Daniel

Faviet

DFAVIET

515.124.4169

******

100

108

110

John

Chen

JCHEN

515.124.4269

******

100

108

111

Ismael

Sciarra

ISCIARRA

515.124.4369

******

100

108

112

Jose Manuel

Urman

JMURMAN

515.124.4469

******

100

108

113

Luis

Popp

LPOOP

133.444.5555

6900

100

108

HRデモ(2) - HRMGRとしてログインについて

表8-2に、HRマネージャHRMGRとしてログインした場合にアクセスできる従業員レコードを示します。すべての従業員の給与情報を表示でき、すべての従業員の連絡先情報を更新できます。

このアクセス権は、次のレルムおよび権限付与によって設定されます: DEPARTMENT_ID in (60, 100)SELECTUPDATEおよびVIEW_SENSITIVE_INFO to HRMGR

給与は、ユーザーに表示権限がある場合にのみ表示され、更新権限がある場合はリンクとしてIDが示されます(表にイタリック形式で)。

例8-2 セッション・サービスHRデモ(2) - HRマネージャHRMGRとしてログイン

ID 電子メール 電話番号 給与 部門ID マネージャID

103

Alexander

Hunold

AHUNOLD

510.222.3388

9000

60

102

104

Bruce

Ernst

BERNST

590.423.4568

6000

60

103

105

David

Austin

DAUSTIN

590.423.4569

4800

60

103

106

Valli

Pataballa

VPATABAL

590.423.4560

4800

60

103

107

Diana

Lorentz

DLORENTZ

590.423.4567

4200

60

103

108

Nancy

Greenberg

NGREENBE

515.124.4569

12008

100

101

109

Daniel

Faviet

DFAVIET

515.124.4169

9000

100

108

110

John

Chen

JCHEN

515.124.4269

8200

100

108

111

Ismael

Sciarra

ISCIARRA

515.124.4369

7700

100

108

112

Jose Manuel

Urman

JMURMAN

515.124.4469

7800

100

108

113

Luis

Popp

LPOOP

133.444.5555

6900

100

108

HRデモ(3) - チーム・マネージャとしてログインについて

表8-3に、チーム・マネージャAHUNOLDとしてログインした場合にアクセスできる従業員レコードを示します。チーム・マネージャの給与情報は表示できますが、彼らの連絡先情報は更新できず、自分の連絡先情報のみ更新できます。

このアクセス権は、次のレルムおよび権限付与によって設定されます: is my member(employee_id) =1VIEW_SENSITIVE_INFO to EMP

給与は、ユーザーに表示権限がある場合にのみ表示され、更新権限がある場合はリンクとしてIDが示されます(表にイタリック形式で)。

例8-3 セッション・サービスHRデモ(3) - チーム・マネージャAHUNOLDとしてログイン

ID 電子メール 電話番号 給与 部門ID マネージャID

103

Alexander

Hunold

AHUNOLD

510.222.3388

9000

60

102

104

Bruce

Ernst

BERNST

590.423.4568

6000

60

103

105

David

Austin

DAUSTIN

590.423.4569

4800

60

103

106

Valli

Pataballa

VPATABAL

590.423.4560

4800

60

103

107

Diana

Lorentz

DLORENTZ

590.423.4567

4200

60

103

108

Nancy

Greenberg

NGREENBE

515.124.4569

******

100

101

109

Daniel

Faviet

DFAVIET

515.124.4169

******

100

108

110

John

Chen

JCHEN

515.124.4269

******

100

108

111

Ismael

Sciarra

ISCIARRA

515.124.4369

******

100

108

112

Jose Manuel

Urman

JMURMAN

515.124.4469

******

100

108

113

Luis

Popp

LPOOP

133.444.5555

******

100

108