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 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で構成されています。
-
セッションの連結、連結解除、破棄(「アプリケーション・セッションAPIについて」を参照)
-
権限の昇格の提供(「権限昇格APIについて」を参照)
-
ネームスペース操作の提供(「ネームスペースAPIについて」を参照)
-
認可の提供(「権限確認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ストアからセッション・マネージャの資格証明を取得するには、コード・ベース権限CredentialAccessPermission
をxsee.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リリースの両方に使用できます。
自動構成について
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
パラメータ
パラメータ | 説明 |
---|---|
|
データベース・サーバー・ラウンドトリップのJDBC接続 |
例
アプリケーション・セッションからの連結解除
現在のユーザーのアプリケーション・セッションを、特定のデータベース接続から連結解除します。
アプリケーション・セッションを常にアプリケーション・コードの最終ブロックから連結解除することをお薦めします。そうしないと、連結された接続が正しいユーザーの下で実行されていないコードに付与されることがあります。使用後にアプリケーション・セッションを適切に連結解除することは、コール元の責任です。
連結解除がコールされずに、同じ接続で連結が再度コールされると、サーバーは前に連結されたアプリケーション・セッションからの連結解除を施行して、現在のアプリケーション・セッションに連結します。
構文
public static void detachSession(java.sql.Connection conn) throws ApplicationSessionException
パラメータ
パラメータ | 説明 |
---|---|
|
データベース・サーバー・ラウンドトリップの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
パラメータ
パラメータ | 説明 |
---|---|
|
データベース・サーバー・ラウンドトリップの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
パラメータ
パラメータ | 説明 |
---|---|
|
データベース・サーバー・ラウンドトリップのJDBC接続 |
|
特定の動的ロール、リクエスト範囲である必要があります |
例
使用上の注意
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
パラメータ
パラメータ | 説明 |
---|---|
|
データベース・サーバー・ラウンドトリップのJDBC接続 |
|
特定のネームスペース名 |
例
例8-6を参照してください。
ネームスペースの削除について
現在のアプリケーション・セッションからネームスペースを削除します。指定されたネームスペースがデータベースで事前定義されていて、アプリケーション・セッションでADMIN_ANY_NAMESPACE
権限が有効化されている場合を除き、連結されたアプリケーション・セッションがMODIFY_NAMESPACE
操作を実行することをネームスペースACLで許可する必要があります。
構文
public static void deleteNamespace(java.sql.Connection conn, java.lang.String name) throws NamespaceNotFoundException, ApplicationSessionException
パラメータ
パラメータ | 説明 |
---|---|
|
データベース・サーバー・ラウンドトリップのJDBC接続 |
|
特定のネームスペース名。 |
例
例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
パラメータ
パラメータ | 説明 |
---|---|
|
データベース・サーバー・ラウンドトリップのJDBC接続 |
|
特定のネームスペース名 |
|
特定のネームスペース属性名 |
|
特定のネームスペース属性値 |
例
例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
パラメータ
パラメータ | 説明 |
---|---|
|
データベース・サーバー・ラウンドトリップのJDBC接続 |
|
特定のネームスペース名 |
|
特定のネームスペース属性名 |
例
例8-6を参照してください。
ネームスペース属性の取得
現在のアプリケーション・セッションでネームスペースから属性を取得します。特定のネームスペースを作成する必要があります。データベース接続は不要で、この操作に対する権限はチェックされません。
ネームスペースを変更するAPI(getNamespaceAttribute
以外)は、入力パラメータとしてデータベース接続を持ちます。これらのAPIは、JVMの現在のアプリケーション・セッションでネームスペースを更新し、変更内容をデータベース表にシリアライズします。接続は連結する必要があります。連結されたアプリケーション・セッションを使用して、サーバーがネームスペースの変更を認可できるかどうかを特定します。
特定の信頼できるアプリケーション・コードにのみ、ネームスペースの設定を許可します。接続は、ネームスペースで昇格権限(MODIFY_NAMESPACE
、MODIFY_ATTRIBUTE
)を持つ動的ロールで連結できます。これは、attachSessionPrivileged
APIを使用し、ネームスペース権限のみを動的ロールに付与することで実現できます。
構文
public static java.lang.String getNamespaceAttribute(java.lang.String name, java.lang.String attribute) throws NamespaceNotFoundException, ApplicationSessionException
パラメータ
パラメータ | 説明 |
---|---|
|
特定のネームスペース名 |
|
特定のネームスペース属性名 |
例
例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
パラメータ
パラメータ | 説明 |
---|---|
|
データベース・サーバー・ラウンドトリップのJDBC接続 |
|
行形式での特定のACL ID |
|
特定の権限名 |
例
例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
を作成し、制限された部門の従業員レコードにアクセスするためのEMP
、HRMGR
およびHRREP
権限を付与します。各外部プリンシパル(アプリケーション・ロール:HRREP
、HRMGR
および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.java
、MyUpdate.java
およびLogoutServlet.java
(これは示されていません)を参照します。
MySession
はV$XS_SESSION_ROLES
ビューを問い合せてアプリケーション・セッションのロールを表示し、XS$SESSION
ネームスペースのユーザーを問い合せてアプリケーション・セッションのユーザーを表示し、V$XS_SESSION_NS_ATTRIBUTES
ビューを問い合せてアプリケーション・セッションのネームスペースを表示して、アプリケーション・セッションに連結します。
MyUpdate
はHR.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
表で問合せを実行して、結果を返します。権限がある場合は、ログイン資格証明に応じて、次に説明されている特定タスクを実行できます。
-
従業員として、自分の給与情報は表示できますが、他人の給与情報は表示できず、自分の連絡先情報のみ更新できます。
-
HRマネージャとしてログインしている場合、すべての従業員の給与レコードを表示でき、彼らの連絡先情報を更新できます。
-
HRデモ(3) - チーム・マネージャとしてログインについて
チーム・マネージャとしてログインしている場合、自分のチームの従業員の給与情報のみ表示できますが、彼らの連絡先情報は更新できず、自分の連絡先情報のみ更新できます。
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 (createNamespace
、setNamespaceAttribute
)を設定してネームスペースを作成し、ネームスペース属性を設定します。
例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)
、SELECT
、UPDATE
および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) =1
とVIEW_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 |