Oracle Containers for J2EE
セキュリティ・ガイド
10g(10.1.3.4.0) B50832-01 |
|
この章では、OC4Jで提供されるログイン・モジュールについてと、カスタム・ログイン・モジュールを実装、インストールおよび構成する方法について説明します。内容は次のとおりです。
この項の内容は次のとおりです。
デフォルトでOC4Jは、Sun社のデフォルトJAASログイン構成プロバイダの使用を上書きする、OC4J JVMからのOracleAS JAAS Providerログイン構成プロバイダ(oracle.security.jazn.spi.LoginConfigProvider
)の使用を指定します。
これは、ファイルORACLE_HOME
/j2ee/home/config/jazn.security.props
の次の構成で実行されます。
login.configuration.provider=oracle.security.jazn.spi.LoginConfigProvider
Oracleログイン構成プロバイダでは、ログイン・モジュール構成にsystem-jazn-data.xml
ファイルを使用します。
OC4Jでのログイン・モジュールの使用に関しては、次のことに注意してください。
provider="XML"
の設定が必要です。custom.loginmodule.provider
プロパティに関連する情報は、「<jazn>のログイン・モジュール用設定」を参照してください。
system-jazn-data.xml
またはアプリケーション固有のjazn-data.xml
ファイルで定義されたユーザーおよびロールではなく、認証済サブジェクトに基づいて認可チェックを実行するように指示することができます。role.mapping.dynamic
プロパティに関連する情報は、「<jazn>のログイン・モジュール用設定」を参照してください。認可時にすべての関連プリンシパルを必ず考慮に入れるために、ログイン・モジュールでは、認証プロセスのcommit
フェーズ時に、関連プリンシパル(認証済ユーザーが属するすべてのロールを含む)をサブジェクトに追加する必要があります。
<jazn-loginconfig>
要素)は、アプリケーション固有のjazn-data.xml
ファイル内に置くことはできません。system-jazn-data.xml
内に置く必要があります。Application Server Controlから、またはorion-application.xml
ファイル内でログイン・モジュールを構成する場合、構成はsystem-jazn-data.xml
に自動的に書き出されます。(「orion-application.xml内の<jazn-loginconfig>での設定」も参照してください。)
UserManager
APIの使用はサポートされなくなります。ただし、J2EEのAPIはアプリケーションで引き続き機能します。
system-jazn-data.xml
内に存在する必要があります。
system-jazn-data.xml
の設定を保守管理する方法について説明します。この機能は、setLoginModule
、remLoginModule
、getLoginModuleControlFlagTypes
などのMBean操作を使用して、ログイン・モジュールにも適用されます。
トラブルシューティングのヒント
orion-application.xml
の<jazn>
要素に追加した場合は除きます。
<property name="role.compare.ignorecase" value="false" />
OC4Jでは、標準のJ2EEログイン・モジュールなど、表9-1に示すログイン・モジュールのセットが提供されます。
ログイン・モジュール | 説明 |
---|---|
oracle.security.jazn.login.module. |
ファイルベース・プロバイダまたはOracle Identity Management用のOC4Jログイン・モジュール(追加情報が続きます。) |
oracle.security.jazn.login.module.db. |
データベース内のユーザー・データ用のOC4Jログイン・モジュール(追加情報が続きます。) |
oracle.security.jazn.login.module. |
関連項目: 第10章「外部LDAPセキュリティ・プロバイダ」 |
oracle.security.jazn.login.module.coreid. |
この項の残りの部分では、次のログイン・モジュールの追加情報を扱います。
RealmLoginModule
クラスは、ファイルベース・プロバイダまたはOracle Identity Managementで使用するデフォルトのログイン・モジュールで、Application Server Controlからセキュリティ・プロバイダを構成するときに構成されます。この構成は、system-jazn-data.xml
ファイルの<jazn-loginconfig>
の下の<login-module>
要素に反映されます。
RealmLoginModule
クラスでは、ユーザーがJ2EEアプリケーションにアクセスする前にユーザー・ログイン資格証明が認証されます。認証は、OC4Jコンテナベース認証(HTTP Basic、フォームベースなど)を使用して実行されます。
RealmLoginModule
は、表9-2に示すオプションをサポートします(<login-module>
の下の<option>
要素の<name>
および<value>
サブ要素に反映されます)。
関連項目
|
次に、system-jazn-data.xml
内のRealmLoginModule
の構成のサンプルを示します。(RealmLoginModule
構成は手動で変更しないでください。この例は単に説明用です。)
<jazn-loginconfig> <application> <name>oracle.security.jazn.tools.Admintool</name> <login-modules> <login-module> <class>oracle.security.jazn.realm.RealmLoginModule</class> <control-flag>required</control-flag> <options> <option> <name>debug</name> <value>false</value> </option> <option> <name>addAllRoles</name> <value>true</value> </option> </options> </login-module> </login-modules> </application> <application> <name>oracle.security.jazn.oc4j.JAZNUserManager</name> <login-modules> <login-module> <class>oracle.security.jazn.realm.RealmLoginModule</class> <control-flag>required</control-flag> <options> <option> <name>addAllRoles</name> <value>true</value> </option> </options> </login-module> </login-modules> </application> </jazn-loginconfig>
OC4J 10.1.3.1実装は、データベースにユーザー・アイデンティティ・ストアがある場合に使用できるログイン・モジュールを提供します。
oracle.security.jazn.login.module.db.DBTableOraDataSourceLoginModule
これにより、現在では非推奨になったcom.evermind.sql.DataSourceUserManager
クラスの前の機能が置き換えられます(このクラスは、下位互換性を維持するため引き続きサポートされ、資料を完全なものにするためにこの項の終わりに掲載されています)。また、非推奨のcom.evermind.security.User
クラスの認証機能の一部も置き換えられます。
データベース・スキーマと、データベースに接続するOracleデータソースを作成すると(『Oracle Containers for J2EEサービス・ガイド』のデータソースの章を参照)、ログイン・モジュールを構成する準備が整います。
DBTableOraDataSourceLoginModule
は、データ・ロケーション(表名や列名)やパスワード暗号化のような項目を指定するいくつかのオプションをサポートします。これらのオプションは、Application Server ControlまたはOracleAS JAAS Provider Admintoolから設定できます。設定はsystem-jazn-data.xml
ファイルの<jazn-loginconfig>
要素に反映されます。
この項の内容は次のとおりです。
表9-3にDBTableOraDataSourceLoginModule
がサポートするオプションを要約しています。どのオプションが必須であるかを示し、適用できるデフォルト値や適切な例などを記載しています。出荷時のOC4Jにはこのログイン・モジュールの構成はありません。ログイン・モジュールの構成に使用できるツールの詳細は、後続の「Application Server Control内のDBTableOraDataSourceLoginModuleの構成」および「AdmintoolのDBTableOraDataSourceLoginModuleの構成」の項を参照してください。
DBTableOraDataSourceLoginModule
は、データベース表内の暗号化されたパスワードをサポートします。カスタム・パスワード暗号化アルゴリズムを使用できます。この機能を使用するには、次のインタフェースを実装する必要があります。「パスワード暗号化のDBLoginModuleEncodingInterfaceの実装」を参照してください。
oracle.security.jazn.login.module.db.DBLoginModuleEncodingInterface
OracleはSHA1およびMD5アルゴリズムの実装を提供しています。
「Application Server Controlでのカスタム・セキュリティ・プロバイダの構成」では、デプロイ時のカスタム・ログイン・モジュールの指定と構成、デプロイ後のカスタム・ログイン・モジュールの変更、ログイン・モジュールの追加、ログイン・モジュールの更新について説明します。ここに示す手順でDBTableOraDataSourceLoginModule
を構成できます。Application Server Controlコンソール・ログイン・モジュール構成ページでは、ログイン・モジュール・クラスを指定し、前項の「DBTableOraDataSourceLoginModuleオプション」に記載されたオプションに対応する任意の数のプロパティの名前と値を指定します。
Application Server Controlコンソールを使用する以外の方法として、OracleAS JAAS Provider AdmintoolからDBTableOraDataSourceLoginModule
を構成することもできます。ログイン・モジュールでのAdmintoolの使用は、「Admintoolを使用したログイン・モジュールの構成とRMIパーミッションの付与」を参照してください。
次に例を示します。
java -jar jazn.jar -addloginmodule application_name \ oracle.security.jazn.login.module.db.DBTableOraDataSourceLoginModule \ required data_source_name="jdbc/OracleDS" roles_fk_column="username" \ table="userinfo" groupMembershipTableName="groupinfo" \ groupMembershipGroupFieldName="role" usernameField="username" \ user_pk_column="username" passwordField="password" casing="sensitive"
ログイン・モジュールと同様に、オプション設定およびその他の構成は、system-jazn-data.xml
ファイルの<jazn-loginconfig>
要素内に格納されます。次に例を示します。
<jazn-loginconfig> <application> <name>application_name</name> <login-modules> <login-module> <class> oracle.security.jazn.login.module.db.DBTableOraDataSourceLoginModule </class> <control-flag>required</control-flag> <options> <option> <name>data_source_name</name> <value>jdbc/OracleDS</value> </option> <option> <name>table</name> <value>userinfo</value> </option> <option> <name>roles_fk_column</name> <value>userName</value> </option> <option> <name>groupMembershipGroupFieldName</name> <value>role</value> </option> <option> <name>user_pk_column</name> <value>userName</value> </option> <option> <name>passwordField</name> <value>passWord</value> </option> <option> <name>groupMembershipTableName</name> <value>groupinfo</value> </option> <option> <name>usernameField</name> <value>userName</value> </option> <option> <name>casing</name> <value>sensitive</value> </option> </options> </login-module> </login-modules> </application> ... </jazn-loginconfig>
DBTableOraDataSourceLoginModule
は次のプリンシパルを使用します。
oracle.security.jazn.login.module.db.principals.DBUserPrincipal
(ユーザー用)
oracle.security.jazn.login.module.db.principals.DBRolePrincipal
(ロール用)
DBTableOraDataSourceLoginModule
に渡されるサブジェクトには、これらプリンシパル・タイプのインスタンスが埋め込まれます。
ユーザー表内のユーザー名(table
オプションで指定された表の、usernameField
オプションで指定された列内の名前)には、対応するDBUserPrincipal
インスタンスがサブジェクト内にあります。
ロール表内のロール名(groupMembershipTableName
オプションで指定された表の、groupMembershipGroupFieldName
オプションで指定された列内の名前)には、対応するDBRolePrincipal
インスタンスがサブジェクト内にあります。
ユーザーまたはロールへのパーミッションの付与には、次のようにAdmintoolを使用できます。
% java -jar jazn.jar -grantperm \ oracle.security.jazn.login.module.db.principals.DBUserPrincipal name \ permissionclass [permission_parameters] % java -jar jazn.jar -grantperm \ oracle.security.jazn.login.module.db.principals.DBRolePrincipal name \ permissionclass [permission_parameters]
この構文で、name
は、DBUserPrincipal
インスタンスまたはDBRolePrincipal
インスタンスの名前です。permissionclass
は、付与するパーミッションのパーミッション・クラスの完全修飾名です。permission_parameters
はパーミッション・クラス(たとえば、RMIPermission
のlogin
)の該当するパラメータです。
DBTableOraDataSourceLoginModule
でパスワードを暗号化するには、暗号化を実行するための次のインタフェースの実装を使用する必要があります。
oracle.security.jazn.login.module.db.DBLoginModuleEncodingInterface
実装するクラスには、ログイン・モジュールから呼び出される次のメソッドを実装する必要があります。
このメソッドは、暗号化するテキスト文字列(パスワードなど)、および(適用可能な場合)ログイン・モジュールのpw_key
オプションに設定されているようなキーを指定する文字列を取ります。このメソッドは、(指定されている場合はキーを使用して)所定のアルゴリズムでテキスト文字列を暗号化し、必要に応じて、所定のエンコード規格(たとえば、Base64Encoding
)で暗号化後のバイナリ・データをフォーマットします。暗号化されたダイジェスト文字列を出力します。
MD5やSHA1など、キーを使用しないアルゴリズムでは、キーを渡しても無視されます。pw_key
オプションが設定されていない場合、値はnull
となり、null
が渡されます。
Oracleでは、oracle.security.jazn.login.module.db.util
パッケージに次の実装を提供します。
DBLoginModuleSHA1Encoder
このクラスは、指定したパスワード文字列のハッシュ値をSHA1アルゴリズムで生成し、バイナリ・ハッシュをBase64Encoding
でエンコードします。パスワードのバイナリ・ハッシュは、Base64Encoding
を使用してデータベースに格納されます。
DBLoginModuleMD5Encoder
このクラスは、指定したパスワード文字列のハッシュ値をMD5アルゴリズムで生成し、バイナリ・ハッシュをBase64Encoding
でエンコードします。パスワードのバイナリ・ハッシュは、Base64Encoding
を使用してデータベースに格納されます。
DBLoginModuleClearTextEncoder
暗号化クラスを指定しない場合、DBLoginModuleClearTextEncoder
が使用され、暗号化は行われません。このクラスは、指定したパスワード文字列を単に渡すだけです。
OC4J 10.1.3.1実装でDBTableOraDataSourceLoginModule
を実装する以前は、com.evermind.sql.DataSourceUserManager
クラスによって同等の機能が使用できていました。この機能は下位互換性を維持するために現在でもサポートされていますが、非推奨であり、将来のリリースではサポートされなくなります。かわりにDBTableOraDataSourceLoginModule
を使用してください。
しかし、資料を完全なものにするため、DataSourceUserManager
機能についても資料に記載しています。
DataSourceUserManager
(後述)を構成する際、必要に応じて表9-4に記載するプロパティの値を指定できます。DataSourceUserManager
インスタンスでは、これらのプロパティを使用して、現行の各ユーザーと関連する資格証明がリストされているユーザー定義のデータベース表にアクセスします。
DataSourceUserManager
を使用するには、orion-application.xml
ファイルの<user-manager>
要素で構成します。これは<orion-application>
のサブ要素であり、手動で構成する必要があります。Application Server Control 10.1.3.x実装では、UserManager
はサポートされていません。
<user-manager>
のclass
属性にDataSourceUserManager
の完全修飾名を指定します。<property>
サブ要素を使用して、設定する各プロパティの名前と値を指定します。
次に例を示します。
<orion-application ... > ... <user-manager class="com.evermind.sql.DataSourceUserManager"> <property name="dataSource" value="jdbc/OracleCoreDS" /> <property name="table" value="j2ee_users" /> <property name="usernameField" value="username" /> <property name="passwordField" value="password" /> <property name="groupMembershipTableName" value="second_table" /> <property name="groupMembershipGroupFieldName" value="group" /> <property name="groupMembershipUserNameFieldName" value="userId" /> </user-manager> ... </orion-application>
OC4JでサポートされるJAASはJAAS 1.0仕様に完全準拠しているので、ユーザーは、必要に応じてJAAS準拠LoginModule
実装をプラグインできます。(OC4Jには、デフォルトのログイン・モジュール実装としてRealmLoginModule
クラスが組み込まれています。このクラスは、ファイルベース・プロバイダまたはOracle Identity Managementと、J2EEセキュリティ制約を結び付けます。)
ユーザーとロールが外部リポジトリで定義されている場合などは、カスタム・ログイン・モジュールの使用をお薦めします。カスタム・ログイン・モジュールの作成時に、次の前提事項を考慮してください。
RealmLoginModule
では、診断出力を提供するdebug
オプションがサポートされます。また、「カスタム・ログイン・モジュールの例」にもデバッグ機能が含まれています。)
カスタム・ログイン・モジュールをアプリケーションと関連付ける場合(後述する構成によって)、サブジェクトおよびそれに含まれるプリンシパルは、J2EEセキュリティ制約の評価などの認可タスクすべてに対する唯一の基礎として使用される必要があります。認可時にすべての関連プリンシパルを必ず考慮に入れるために、ログイン・モジュールでは、認証プロセスのコミット・フェーズで、関連プリンシパル(認証済ユーザーが属するすべてのロールなど)をサブジェクトに追加する必要があります。(サブジェクトベースの認可は、role.mapping.dynamic
プロパティと関係があります。詳細は「<jazn>のログイン・モジュール用設定」を参照してください。)
カスタム・ログイン・モジュール・フレームワークでは、J2EEの宣言によるセキュリティ・モデルをサポートします。つまり、サブジェクトベースの認可により、アプリケーション・デプロイメント・ディスクリプタ(web.xml
およびejb-jar.xml
など)に宣言されているJ2EEのセキュリティ制約が施行されます。
カスタム・ログイン・モジュールはOC4Jのsystem-jazn-data.xml
ファイルを介して構成しますが、このファイルは、Application Server ControlコンソールやOracleAS JAAS Provider Admintoolなどのツールを使用して自動的に更新できます。ログイン・モジュールをorion-application.xml
によって構成することもできます。この場合、構成はsystem-jazn-data.xml
にコピーされます。
関連項目
|
OC4JまたはJ2SEで提供されるデフォルト・ログイン・モジュールを1つ以上使用する場合、追加の構成は必要ありません。OracleAS JAAS Providerは、デフォルト・ログイン・モジュールを検出できます。
1つ以上のカスタム・ログイン・モジュールとともにアプリケーションをデプロイする場合は、ログイン・モジュールをデプロイし、そのモジュールを実行時に検出できるようにOracleAS JAAS Providerを適切に構成する必要があります。以降の各項では、その実行方法について説明します。
この項では、これらのオプションの詳細を説明します。
ログイン・モジュールが単一のJ2EEアプリケーションでしか使用されない場合は、アプリケーションEARファイルにログイン・モジュールJARファイルを追加して、ログイン・モジュールをアプリケーションの一部としてそのままパッケージ化できます。
ログイン・モジュールは、次の2箇所にあるいずれかの<jazn-loginconfig>
設定を介して構成する必要があります。
system-jazn-data.xml
ファイル内(「system-jazn-data.xml内のログイン・モジュール設定」を参照)
orion-application.xml
ファイル内(「orion-application.xml内の<jazn-loginconfig>での設定」を参照)
カスタム・ログイン・モジュールは、アプリケーションのデプロイ時、または後で(セキュリティ・プロバイダをカスタムに変更する場合)、Application Server Controlコンソールを使用して構成できます。構成を行うと、system-jazn-data.xml
が自動的に更新されます。
また、OracleAS JAAS Provider Admintoolを介してカスタム・ログイン・モジュールの管理を行った場合にも、system-jazn-data.xml
設定が自動的に更新されます。
ログイン・モジュールをオプション・パッケージ(旧称「標準拡張機能」)としてデプロイすると、それをOracleAS JAAS Providerで検出できます。追加構成は不要です。この方法でデプロイしたログイン・モジュールは、複数のアプリケーションで共有できます。
オプション・パッケージとしてデプロイするには、次の2つの方法があります。
jre/lib/ext
ディレクトリに入れます。アプリケーションは、このディレクトリのJARファイル内のクラスを、クラスパスに追加しないでも使用できるようになります。
Class-Path
ヘッダー・フィールドに、ログイン・モジュールJARファイルを指定します。これにより、ログイン・モジュールJARファイルに含まれるクラスが、それを参照する他のJARファイルのクラスから使用できるようになります。
また、ログイン・モジュールは、system-jazn-data.xml
内にも構成する必要があります(「system-jazn-data.xml内のログイン・モジュール設定」を参照)。
OracleAS JAAS Providerは、OC4Jのクラス・ロード・アーキテクチャと統合されています。このため、ログイン・モジュールは、OC4J共有ライブラリとしてロードすることで、アプリケーションで使用できるようになります。「ライブラリを共有するためのタスク」を参照してください。
この項では、Application Server Controlコンソールを使用したカスタム・セキュリティ・プロバイダ(カスタム・ログイン・モジュール)の次の管理タスクについて説明します。
注意
oc4jadmin
など)としてログインしてください。
「ライブラリを共有するためのタスク」を参照してください。)
カスタム・セキュリティ・プロバイダの使用を計画している場合は、Application Server Controlを介してアプリケーションをデプロイする際に、カスタム・ログイン・モジュールを構成できます。
「デプロイ: デプロイ設定」ページで、次の手順を実行します(このページへのナビゲート方法は、「Application Server Controlを介したアプリケーションのデプロイ」を参照してください)。
Application Server Controlからカスタム・ログイン・モジュールをデプロイまたは構成すると、orion-application.xml
ファイルに次の設定が自動的に挿入されます。
<jazn provider="XML"> <property name="role.mapping.dynamic" value="true" /> <property name="custom.loginmodule.provider" value="true" /> </jazn>
注意
|
関連項目
|
カスタム・セキュリティ・プロバイダを使用するアプリケーションのデプロイ時にカスタム・ログイン・モジュールを編集するには、「デプロイ設定: セキュリティ・プロバイダの選択」ページ(このページへのナビゲート方法は、前述の「デプロイ時のカスタム・セキュリティ・プロバイダの指定および構成」を参照)の「カスタム・セキュリティ・プロバイダの構成」を選択して、次の手順を実行します。
これらの制御フラグはjavax.security.auth.login.Configuration
クラスの標準機能によって使用されます。全体の認証は、RequiredおよびRequisiteのログイン・モジュールがすべて成功した場合にのみ成功します。ただし、Sufficientのログイン・モジュールが構成されていて成功した場合には、ログイン・モジュール・リスト内のSufficientのログイン・モジュールの前にあるRequiredおよびRequisiteのログイン・モジュールのみ成功する必要があります。
カスタム・セキュリティ・プロバイダを使用するアプリケーションのデプロイ時にカスタム・ログイン・モジュールを追加するには、「デプロイ設定: セキュリティ・プロバイダの選択」ページ(このページへのナビゲート方法は、前述の「デプロイ時のカスタム・セキュリティ・プロバイダの指定および構成」を参照)の「カスタム・セキュリティ・プロバイダの構成」を選択して、次の手順を実行します。
アプリケーションで使用するセキュリティ・プロバイダは、前述のようにデプロイ時に選択できます。また、デプロイ後に、異なるセキュリティ・プロバイダに変更することもできます。カスタム・セキュリティ・プロバイダには次の手順で変更できます。
ここで、「セキュリティ・プロバイダ」ページに戻り、変更を反映するためにアプリケーションを再起動するよう求められます。
デプロイ時またはデプロイ後にカスタム・セキュリティ・プロバイダを設定後、カスタム・ログイン・モジュールを追加するには次のようにします。
「セキュリティ・プロバイダ」ページが再表示されます。このページで設定を確認できます。
デプロイ時またはデプロイ後にカスタム・セキュリティ・プロバイダを設定後、カスタム・ログイン・モジュールを更新するには次のようにします。
これにより、引き続き「ログイン・モジュールの編集」ページが表示されます。ページ上部のブレッドクラムを使用すると、「セキュリティ・プロバイダ」ページに戻れます。
デプロイ時またはデプロイ後にカスタム・セキュリティ・プロバイダを設定後、カスタム・ログイン・モジュールを削除するには次のようにします。
「セキュリティ・プロバイダ」ページが再表示されます。このページでログイン・モジュールが削除されたことを確認できます。
この項では、次の状況でOracleAS JAAS Provider Admintoolを使用する方法について説明します。
カスタム・ログイン・モジュールの追加および構成用の推奨ツールはApplication Server Controlですが、OracleAS JAAS Provider Admintoolを使用することもできます。次の情報を参照してください。
-addloginmodule
: 指定したアプリケーション用に新規ログイン・モジュールを構成します。この際、制御フラグの指定が必要です。javax.security.auth.login.Configuration
および表9-5に規定されているように、Required
、Requisite
、Sufficient
またはOptional
のいずれかを指定する必要があります。ログイン・モジュールがオプションをサポートする場合は、各オプションとその値をoptionname=value
のペアとして指定します。各ログイン・モジュールには、独自の個別オプション・セットがあります。
たとえば、debug
をtrue
に設定して、必須モジュールとしてMyLoginModule
(debug
オプションをサポートすると想定)をアプリケーションmyapp
に追加するには、次のように入力します。
% java -jar jazn.jar -addloginmodule myapp MyLoginModule required debug=true
-remloginmodule
: 指定されたログイン・モジュールを削除します。MyLoginModule
をmyapp
から削除するには、次のように入力します。
% java -jar jazn.jar -remloginmodule myapp MyLoginModule
-listloginmodules
: 指定のアプリケーションのログイン・モジュールをすべて表示します。アプリケーション名を指定しない場合は、すべてのアプリケーションのログイン・モジュールを表示します。アプリケーション名の後にログイン・モジュール・クラスを指定すると、そのアプリケーションにある指定クラス関連情報のみが表示されます。たとえば、アプリケーションmyapp
のログイン・モジュールをすべて表示するには、次のように入力します。
% java -jar jazn.jar -listloginmodules myapp
これらのコマンドは、Admintoolシェルから実行することもできます。
アプリケーションにEJBが含まれる場合、RMIを介してEJBにアクセスするには、適切なユーザー、ロールまたはプリンシパルに対してRMIパーミッションのloginを付与する必要があります。これには、次の例に示すようにAdmintoolを使用できます。
% java -jar jazn.jar -grantperm myrealm -role managers \ com.evermind.server.rmi.RMIPermission login % java -jar jazn.jar -grantperm oracle.security.jazn.samples.SamplePrincipal \ managers com.evermind.server.rmi.RMIPermission login
(ユーザーまたはロールにパーミッションを付与するときには常にレルムを指定しますが、プリンシパルにパーミッションを付与するときには指定しません。)
Oracle Application Server環境に複数のOC4Jインスタンスがある場合、該当のOC4Jインスタンス用のsystem-jazn-data.xml
ファイルが更新されるように、適用するOC4Jインスタンスに対して該当のインスタンス名(および該当のホーム・ディレクトリ)を指定する必要があります。環境に応じて適切に%oracleas.oc4j.instance%
を設定します。
% java -jar -Doracle.j2ee.home=%ORACLE_HOME%/j2ee/%oracleas.oc4j.instance% \ jazn.jar -grantperm myrealm -role managers \ com.evermind.server.rmi.RMIPermission login % java -jar -Doracle.j2ee.home=%ORACLE_HOME%/j2ee/%oracleas.oc4j.instance% \ jazn.jar -grantperm oracle.security.jazn.samples.SamplePrincipal managers \ com.evermind.server.rmi.RMIPermission login
この項では、カスタム・ログイン・モジュールの構成を含む各ファイルについて説明します。
system-jazn-data.xml
ファイルは、ログイン・モジュール構成のリポジトリです。
Application Server ControlまたはOracleAS JAAS Provider Admintoolを介してログイン・モジュールの管理を行うと、system-jazn-data.xml
の設定が自動的に更新されます。
<jazn-loginconfig>
要素には、アプリケーションをログイン・モジュールに関連付ける情報が含まれます。
デプロイ時にこの情報がorion-application.xml
ファイルにある場合(「orion-application.xml内の<jazn-loginconfig>での設定」を参照)、system-jazn-data.xml
ファイルはそれに応じて更新されます。
<jazn-data> .. <jazn-loginconfig> <application> <name>myapp</name> <login-modules> <login-module> <class>mypath.MyLoginModule</class> <control-flag>required</control-flag> <options> <option> <name>myoptionname</name> <value>myoptionvalue</value> </option> </options> </login-module> </login-modules> </application> </jazn-loginconfig> .. </jazn-data>
このフラグメントはログイン・モジュールMyLoginModule
とアプリケーションmyapp
を関連付けます。
この項では、OC4Jアプリケーション・レベルのディスクリプタorion-application.xml
内のログイン・モジュール向けの設定について説明します。内容は次のとおりです。
system-jazn-data.xml
内の<jazn-loginconfig>
要素での設定は、前述の「system-jazn-data.xml内のログイン・モジュール設定」を参照してください。この要素はデプロイの前にorion-application.xml
に追加でき、行った設定はsystem-jazn-data.xml
ファイルに自動的に書き込まれます。また、アプリケーションをアンデプロイすると、<jazn-loginconfig>
設定はsystem-jazn-data.xml
から自動的に削除されます。
次の<jazn>
のプロパティはログイン・モジュール構成固有です。
role.mapping.dynamic
このプロパティをtrue
に設定すると、OracleAS JAAS Providerに対して、system-jazn-data.xml
またはアプリケーション固有のjazn-data.xml
ファイルで定義されたユーザーおよびロールではなく、認証済サブジェクトに基づいて認可チェックを実行するように指示したことになります。
LoginModule
インスタンスでは、認可プロセスでプリンシパルを考慮に入れるために、認証プロセスのコミット・フェーズで適切なプリンシパル(ユーザーまたはロール)がSubject
インスタンスに関連付けられることを保証する必要があります。サブジェクトへのプリンシパルのこの関連付けは、通常、標準のJAAS APIを使用して実装されます。
custom.loginmodule.provider
このプロパティをtrue
に設定すると、Application Server Controlに対して、カスタム・プロバイダをセキュリティ・プロバイダにするよう指示したことになります。この設定がないと、カスタム・セキュリティ・プロバイダでは設定provider="XML"
が使用されるため、Application Server Controlにより、セキュリティ・プロバイダはファイルベース・プロバイダであると誤ってレポートされることになります(ただし、EARファイルで指定したカスタム・ログイン・モジュールはまだ機能します)。
これらのプロパティは、orion-application.xml
に<jazn-loginconfig>
要素があるとき、または「デプロイ時のカスタム・セキュリティ・プロバイダの指定および構成」の説明のようにApplication Server Controlコンソールを使用してカスタム・ログイン・モジュールをデプロイして構成するときは、次の例に示すようにorion-application.xml
内で自動的にtrue
に設定されます。
<jazn provider="XML" ... > <property name="role.mapping.dynamic" value="true" /> <property name="custom.loginmodule.provider" value="true" /> </jazn>
アプリケーションにEJBが含まれている場合は、アプリケーションのサーバー・サイドJNDIコンテキストでオブジェクトの読取り(検索)および書込み(バインド)を行うためのネームスペース・アクセス権を、必要に応じてリモート・クライアントに付与する必要があります。
orion-application.xml
から抜粋した次の例では、読取り操作を行うためのネームスペース・アクセス権をmanagers
およびdevelopers
ロールに付与する方法を示しています。
<orion-application ... > ... <namespace-access> <read-access> <namespace-resource root=""> <security-role-mapping name="sr_developer"> <group name="developers"/> </security-role-mapping> <security-role-mapping name="sr_manager"> <group name="managers"/> </security-role-mapping> </namespace-resource> </read-access> </namespace-access> ... </orion-application>
ここでは、示されたロール・マッピングがすでにorion-application.xml
内で設定されていることを前提にしています。
ログイン・モジュール用に、Oracle Internet Directory(OID)プロバイダのマッピング属性は、デフォルトで"DN"
に設定されます。
このデフォルト値は、mapping.attribute
プロパティの値を構成して変更できます。
$Oracle_Home/j2ee/<oc4j_inst>/config/jazn.xml
ファイルを探します。
mapping.attribute
プロパティ構成を<jazn>タグに追加します。次に例を示します。
<jazn provider... > ... <property name = "mapping.attribute" value="cn"/> ... </jazn>
jazn.xml
ファイルのmapping.attribute
属性に依存するログイン・モジュールは、次のとおりです。
WSSLoginModule
)
SAMLLoginModule
) SAMLLoginModule
は、最初にSubjectNameIdentifier
を参照してマッピングを確認します。空白の場合は、mapping.attribute
を使用します。
X509LoginModule
)
LDAPLoginModule
)
これらのログイン・モジュールのマッピング属性は、前述のようにjazn.xml
ファイルで設定する必要があります。
リソース・アダプタを構成するとき、次の例のように、oc4j-ra.xml
ファイルの各<connector-factory>
要素では、異なるJAASログイン・モジュールを指定できます。この例では、Oracle JDBCを介してデータベースに接続するための<config-property>
の設定も示しています。
<oc4j-connector-factories ... > ... <connector-factory connector-name="myBlackbox" location="eis/myEIS1"> <config-property name="connectionURL" value="jdbc:oracle:thin:@localhost:5521/myservice" /> <security-config use="jaas-module"> <jaas-module> <jaas-application-name>JAASModuleDemo</jaas-application-name> </jaas-module> </security-config> </connector-factory> ... </oc4j-connector-factories>
ログイン・モジュールの開発作業は、標準的な開発、パッケージ化およびデプロイのサイクルをたどります。EJBを含むアプリケーションでは、RMIパーミッションを付与し、必要に応じてネームスペース・アクセス権を構成する必要があります。以降の各項では、このサイクルの各ステップについて説明します。
JAASサービス・プロバイダ・インタフェースに従ってJAAS準拠のLoginModule
実装を開発します。
ログイン・モジュールをアプリケーションと関連付けるとき(前述の<jazn-loginconfig>
構成で実行)、OC4Jはサブジェクトに設定されたプリンシパルを使用して、要求されたJ2EEリソースへのアクセス権をクライアントが持っているかどうかを調べます。したがって、ログイン・モジュールはロール、ユーザーがメンバーとなっているロールをすべて正しく設定する必要があります。
次の例では、ログイン・モジュールはdeveloper
ユーザーを認証します。ユーザーが正常に認証された後、ユーザーに関連付けられたロールに対応するプリンシパルが、現在認証されたサブジェクトに追加されます。developer
ユーザーがdevelopers
ロールのメンバーであることを想定しています。
if(username.equals("developer") && password.equals("welcome")) { _succeeded = true; _name = "developer"; _password = password.toCharArray(); _authPrincipals = new SamplePrincipal[2]; //Adding username as principal to the subject _authPrincipals[0] = new SamplePrincipal("developer"); //Adding role developers to the subject _authPrincipals[1] = new SamplePrincipal("developers"); }
関連項目
|
「ログイン・モジュールのパッケージ化の選択の概要」では、アプリケーションにアクセスできるようにログイン・モジュールをパッケージ化する様々な方法をまとめています。各選択肢を次に示します。
ログイン・モジュールの構成を指定できる方法にはいくつかの選択肢があります。
orion-application.xml
ファイルの<jazn-loginconfig>
要素を手動で構成します。「orion-application.xml内の<jazn-loginconfig>での設定」を参照してください。特に、ログイン・モジュールとご使用のアプリケーションをパッケージ化する場合に役立ちます。それに応じてsystem-jazn-data.xml
内の<jazn-loginconfig>
要素も更新されます。
system-jazn-data.xml
内の<jazn-loginconfig>
要素が自動的に構成されます。
system-jazn-data.xml
内の<jazn-loginconfig>
要素が自動的に構成されます。
次の項では、キーの構成を中心に説明します。
OC4Jでは、セキュリティ・チェックを実行するカスタム・ログイン・モジュールを使用するためにorion-application.xml
ファイルに次の構成を必要とします。これは、Application Server Controlまたはorion-application.xml
でログイン・モジュール構成を指定すると、自動的に実行されます。
<jazn provider="XML" > <property name="role.mapping.dynamic" value="true"/> <property name="custom.loginmodule.provider" value="true"/> </jazn>
デプロイ後にorion-application.xml
ファイルを調べてこれを確認できます。
次の構成は、「カスタム・ログイン・モジュールの例」に示すログイン・モジュールのサンプルです。
<!-- Configuring a Login Module in an Application EAR file. --> <jazn-loginconfig> <application> <name>cutomjaas</name> <login-modules> <login-module> <class>oracle.security.jazn.samples.SampleLoginModule</class> <control-flag>required</control-flag> <options> <option> <name>debug</name> <value>true</value> </option> </options> </login-module> </login-modules> </application> </jazn-loginconfig>
デプロイ前にこの構成を手動でorion-application.xml
ファイル内に配置することも、Application Server Controlからアプリケーションをデプロイする場合に、デプロイ中にプロンプトに応じてパラメータ(クラス名、制御フラグ、オプション名および値)を設定することもできます。いずれの場合も、構成は自動的にsystem-jazn-data.xml
に書き込まれます。
アプリケーションにEJBが含まれる場合、orion-application.xml
内にネームスペース・アクセス権を構成します。これは、アプリケーションのサーバー・サイドJNDIコンテキストのオブジェクトで、必要に応じて、リモート・クライアントが読取り(検索)操作または書込み(バインド)操作のJNDIバインディングにアクセスできるようにします。次の例に、ネームスペース・アクセス権をmanagers
およびdevelopers
という名前のロールに付与する方法を示します。
<orion-application ... > ... <namespace-access> <read-access> <namespace-resource root=""> <security-role-mapping name="sr_developer"> <group name="developers"/> </security-role-mapping> <security-role-mapping name="sr_manager"> <group name="managers"/> </security-role-mapping> </namespace-resource> </read-access> </namespace-access> ... </orion-application>
これは、次のorion-application.xml
の例に示すように、ロール・マッピング(アプリケーション内で定義された論理ロールの、カスタム・ログイン・モジュールでサポートされるロールへのマッピング)が適切に定義されていることを前提としています。
<orion-application ... > ... <!-- Mapping the logical roles to the container roles --> <security-role-mapping name="sr_manager"> <group name="managers" /> </security-role-mapping> <security-role-mapping name="sr_developer"> <group name="developers" /> </security-role-mapping> ... </orion-application>
ロール・マッピングはApplication Server Controlから指定できます。「セキュリティ・ロールのマッピング」を参照してください。これにより、orion-application.xml
のエントリが自動的に追加されます。
「ログイン・モジュールのパッケージ化の選択の概要」では、ログイン・モジュールをアプリケーションとともに、または個別に(オプション・パッケージまたは共有ライブラリとして)デプロイする方法について説明します。
「デプロイ時のカスタム・セキュリティ・プロバイダの指定および構成」では、アプリケーションのデプロイ時にApplication Server Controlによってログイン・モジュールを構成してデプロイする方法について説明します。
アプリケーションにEJBが含まれる場合、RMIを介してEJBにアクセスするには、適切なユーザー、ロールおよびプリンシパルに対してRMIパーミッションのloginを付与する必要があります。これには、Admintoolを使用できます。「AdmintoolによるRMIパーミッションの付与」を参照してください。
JNDIを通じてリソースにアクセスするには、jndi.properties
ファイルを構成し、環境に応じてプロバイダURL、プリンシパルおよび資格証明などのプロパティを設定する必要があります。次に例を示します。
java.naming.factory.initial= oracle.j2ee.naming.ApplicationClientInitialContextFactory java.naming.provider.url=ormi://localhost:23791/customjaas #java.naming.provider.url=opmn:ormi://localhost:6003:home/customjaas java.naming.security.principal=manager java.naming.security.credentials=welcome
(ormi
プロトコルはスタンドアロンOC4J用、opmn:ormi
プロトコルはOracle Application Server環境用です。適切な方をコメント解除します。)
この項では、次の場所でのOC4Jの使用方法のサンプルとしてログイン・モジュールのコードとプリンシパルのコードを示します。
http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/index.html
「J2EE Security / JAAS」の下のログイン・モジュールの使用方法を参照してください。
この項では、サンプル・ログイン・モジュールのコードを示します。
package oracle.security.jazn.samples; import java.util.Set; import java.util.Iterator; import java.util.Map; import java.security.Principal; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.Callback; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; public class SampleLoginModule implements LoginModule { // initial state protected Subject _subject; protected CallbackHandler _callbackHandler; protected Map _sharedState; protected Map _options; // configuration options protected boolean _debug; // the authentication status protected boolean _succeeded; protected boolean _commitSucceeded; // username and password protected String _name; protected char[] _password; protected Principal[] _authPrincipals; /* * Initialize this LoginModule. * * subject the Subject to be authenticated. * callbackHandler a CallbackHandler for communicating * with the end user (prompting for usernames and * passwords, for example). * sharedState shared LoginModule state. * options options specified in the login * Configuration for this particular * LoginModule. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { this._subject = subject; this._callbackHandler = callbackHandler; this._sharedState = sharedState; this._options = options; // initialize any configured options _debug = "true".equalsIgnoreCase((String) _options.get("debug")); if (debug()) { printConfiguration(this); } } final public boolean debug() { return _debug; } protected Principal[] getAuthPrincipals() { return _authPrincipals; } /* * Authenticate the user by prompting for a username and password. * * return true if the authentication succeeded, or false if this * LoginModule should be ignored. * throws FailedLoginException if the authentication fails. * throws LoginException if this LoginModule * is unable to perform the authentication. */ public boolean login() throws LoginException { if (debug()) System.out.println("\t\t[SampleLoginModule] login"); if (_callbackHandler == null) throw new LoginException("Error: no CallbackHandler available " + "to garner authentication information from the user"); // Setup default callback handlers. Callback[] callbacks = new Callback[] { new NameCallback("Username: "), new PasswordCallback("Password: ", false) }; try { _callbackHandler.handle(callbacks); } catch (Exception e) { _succeeded = false; throw new LoginException(e.getMessage()); } String username = ((NameCallback)callbacks[0]).getName(); String password = new String(((PasswordCallback)callbacks[1]).getPassword()); if (debug()) { System.out.println("\t\t[SampleLoginModule] username : " + username); } // Authenticate the user. On successfull authentication add principals // to the Subject. The name of the principal is used for authorization by // OC4J by mapping it to the value of the name attribute of the group // element in the security-role-mapping for the application. if(username.equals("developer") && password.equals("welcome")) { _succeeded = true; _name = "developer"; _password = password.toCharArray(); _authPrincipals = new SamplePrincipal[2]; //Adding username as principal to the subject _authPrincipals[0] = new SamplePrincipal("developer"); //Adding role developers to the subject _authPrincipals[1] = new SamplePrincipal("developers"); } if(username.equals("manager") && password.equals("welcome")) { _succeeded = true; _name = "manager"; _password = password.toCharArray(); _authPrincipals = new SamplePrincipal[3]; //Adding username as principal to the subject _authPrincipals[0] = new SamplePrincipal("manager"); //Adding roles developers and managers to the subject _authPrincipals[1] = new SamplePrincipal("developers"); _authPrincipals[2] = new SamplePrincipal("managers"); } if (username.equals("sirish") && password.equals("sirish")) { _succeeded = true; _password = password.toCharArray(); _name = "sirish"; _authPrincipals = new SamplePrincipal[1]; _authPrincipals[0] = new SamplePrincipal("sirish"); } ((PasswordCallback)callbacks[1]).clearPassword(); callbacks[0] = null; callbacks[1] = null; if (debug()) { System.out.println("\t\t[SampleLoginModule] success : " + _succeeded); } if (!_succeeded) throw new LoginException ("Authentication failed: Password does not match"); return true; } /* * This method is called if the LoginContext's * overall authentication succeeded * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules * succeeded). * * If this LoginModule's own authentication attempt * succeeded (checked by retrieving the private state saved by the * login method, then this method associates a * Principal with the Subject located in the * LoginModule. If this LoginModule's own * authentication attempted failed, then this method removes * any state that was originally saved. * * return true if this LoginModule's own login and commit * attempts succeeded, or false otherwise. * throws LoginException if the commit fails. */ public boolean commit() throws LoginException { try { if (_succeeded == false) { return false; } if (_subject.isReadOnly()) { throw new LoginException("Subject is ReadOnly"); } // add authenticated principals to the Subject if (getAuthPrincipals() != null) { for (int i = 0; i < getAuthPrincipals().length; i++) { if(!_subject.getPrincipals().contains(getAuthPrincipals()[i])) { _subject.getPrincipals().add(getAuthPrincipals()[i]); } } } // in any case, clean out state cleanup(); if (debug()) { printSubject(_subject); } _commitSucceeded = true; return true; } catch (Throwable t) { if (debug()) { System.out.println(t.getMessage()); t.printStackTrace(); } throw new LoginException(t.toString()); } } /* * This method is called if the LoginContext's * overall authentication failed. * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules * did not succeed). * * If this LoginModule's own authentication attempt * succeeded (checked by retrieving the private state saved by the * login and commit methods), * then this method cleans up any state that was originally saved. * * return false if this LoginModule's own login and/or commit attempts * failed, and true otherwise. * throws LoginException if the abort fails. */ public boolean abort() throws LoginException { if (debug()) { System.out.println ("\t\t[SampleLoginModule] aborted authentication attempt."); } if (_succeeded == false) { cleanup(); return false; } else if (_succeeded == true && _commitSucceeded == false) { // login succeeded but overall authentication failed _succeeded = false; cleanup(); } else { // overall authentication succeeded and commit succeeded, // but someone else's commit failed logout(); } return true; } protected void cleanup() { _name = null; if (_password != null) { for (int i = 0; i < _password.length; i++) { _password[i] = ' '; } _password = null; } } protected void cleanupAll() { cleanup(); if (getAuthPrincipals() != null) { for (int i = 0; i < getAuthPrincipals().length; i++) { _subject.getPrincipals().remove(getAuthPrincipals()[i]); } } } /* * Logout the user. * * This method removes the Principal * that was added by the commit method. * * return true in all cases since this LoginModule * should not be ignored. * throws LoginException if the logout fails. */ public boolean logout() throws LoginException { _succeeded = false; _commitSucceeded = false; cleanupAll(); return true; } // helper methods // protected static void printConfiguration(SampleLoginModule slm) { if (slm == null) { return; } System.out.println("\t\t[SampleLoginModule] configuration options:"); if (slm.debug()) { System.out.println("\t\t\tdebug = " + slm.debug()); } } protected static void printSet(Set s) { try { Iterator principalIterator = s.iterator(); while (principalIterator.hasNext()) { Principal p = (Principal) principalIterator.next(); System.out.println("\t\t\t" + p.toString()); } } catch (Throwable t) { } } protected static void printSubject(Subject subject) { try { if (subject == null) { return; } Set s = subject.getPrincipals(); if ((s != null) && (s.size() != 0)) { System.out.println ("\t\t[SampleLoginModule] added the following Principals:"); printSet(s); } s = subject.getPublicCredentials(); if ((s != null) && (s.size() != 0)) { System.out.println ("\t\t[SampleLoginModule] added the following Public Credentials:"); printSet(s); } } catch (Throwable t) { } } }
この項では、サンプル・プリンシパルのコードを示します。
ログイン・モジュールは、現在のSubject
インスタンス内のSamplePrincipal
インスタンスを設定します。SamplePrincipal
インスタンスを作成するために、ログイン・モジュールは直接SamplePrincipal
コンストラクタを呼び出します。そのため、コンストラクタはパブリックとして定義します。
package oracle.security.jazn.samples; import java.security.Principal; /* * This class implements the Principal interface * and represents a Sample user. * * Principals such as this SamplePrincipal * may be associated with a particular Subject * to augment that Subject with an additional * identity. Authorization decisions can then be based upon * the Principals associated with a Subject. * */ public class SamplePrincipal implements Principal { private String _name = null; /* * Create a SamplePrincipal with a Sample username. * */ public SamplePrincipal(String name) { if (name == null) throw new NullPointerException("name cannot be null"); _name = name; } /* * Return a string representation of this SamplePrincipal. * */ public String getName() { return _name; } /* * Return a hash code for this SamplePrincipal. * */ public int hashCode() { return _name.hashCode(); } /* * Return a string representation of this SamplePrincipal. * */ public String toString() { return "[SamplePrincipal] : " + _name; } /* * Compares the specified Object with this SamplePrincipal * for equality. Returns true if the given object is also a * SamplePrincipal and the two SamplePrincipals * have the same username. * */ public boolean equals(Object o) { if (o == null) return false; if (this == o) return true; if (!(o instanceof SamplePrincipal)) return false; SamplePrincipal that = (SamplePrincipal)o; if (this.getName().equals(that.getName())) return true; return false; } }
|
Copyright © 2003, 2008 Oracle Corporation. All Rights Reserved. |
|