このチュートリアルでは、「JAAS 認証」チュートリアルで開発したプログラムおよびポリシーファイルを拡張して、JAAS 承認コンポーネントの働きを示します。JAAS 承認コンポーネントは、認証された呼び出し側が、その後のセキュリティ関連の操作に必要なアクセス制御権 (アクセス権) を保持することを保証します。 承認されたコンポーネントでは、ユーザ認証が完了していることが最初に要求されます。このため、「JAAS 認証」チュートリアルを先にお読みください。
このチュートリアルは、次のセクションで構成されます。
チュートリアルのコードを最初に実行してみる場合、「承認チュートリアルコードの実行」を先に読んでから、最初に戻り、学習を続けてください。
JAAS 承認とは
JAAS 承認は、セキュリティポリシーを使用して実行コードに付与するアクセス権を指定する、既存の Java セキュリティアーキテクチャを拡張します。 これは、Java 2 プラットフォームで導入された、「コード中心」のアーキテクチャです。 つまり、アクセス権はコードの特性 (コードの出所、デジタル署名されているかどうか、デジタル署名されている場合はその署名者) に基づいて付与されます。 具体例としては、「JAAS 認証」チュートリアルで使用される
sampleacn.policy
ファイルがあります。 このファイルには、以下が含まれます。grant codebase "file:./SampleAcn.jar" { permission javax.security.auth.AuthPermission "createLoginContext.Sample"; };これにより、現行ディレクトリの
SampleAcn.jar
ファイル内のコードに、指定されたアクセス権が付与されます。 署名者は指定されていないため、コードが署名されているかどうかは問題となりません。JAAS 承認は、既存のコード中心のアクセス制御を「ユーザ中心」のアクセス制御で補強します。 どのコードが実行されているかだけではなく、どの「ユーザ」が実行しているかに基づいて、アクセス制御を実行できるようになっています。
アプリケーションが JAAS 認証を使ってユーザまたはその他のエンティティ (サービスなど) を認証すると、結果としてサブジェクトが生成されます。 サブジェクトは、認証されたユーザを表します。 サブジェクトは、そのユーザの識別情報を表すプリンシパルのセットで構成されます。 さらに、自身をその他のサブジェクトから区別する名前のプリンシパル (「Susan Smith」) や社会保障番号のプリンシパル (「987-65-4321」) などを持つことができます。
ポリシー内で特定のプリンシパルにアクセス権を付与することができます。 ユーザの認証後、アプリケーションはサブジェクトと現在のアクセス制御コンテキストを関連付けることができます。 その後、セキュリティチェックの対象となる操作 (ローカルファイルアクセスなど) のたびに、Java ランタイムにより、ポリシー内で特定のプリンシパルだけに必要なアクセス権が付与されているかどうかの自動確認が行われます。そして、アクセス制御コンテキストに関連付けられたサブジェクトに指定のプリンシパルが含まれている場合にかぎり、その操作が許可されます。
JAAS 承認を実行する前に、次のようにします。
- ユーザを認証します (「JAAS 認証」を参照)。
- セキュリティポリシー内にプリンシパルベースのエントリを構成します。
- 認証の結果生成されたサブジェクトと現在のアクセス制御コンテキストを関連付けます。
プリンシパルのポリシーファイル文の作成方法
ポリシーファイルの
grant
文に、1 つ以上の Principal フィールドをオプションで含めることができるようになりました。 Principal フィールドは、指定されたプリンシパルで表される (指定されたコードを実行する) ユーザまたはその他のエンティティが、特定のアクセス権を保持することを表します。このため、
grant
文の基本的な書式は次のようになります。signer、codeBase、Principal の各フィールドはオプションであり、各フィールドの順序は重要ではありません。grant <signer(s) field>, <codeBase URL> <Principal field(s)> { permission perm_class_name "target_name", "action"; .... permission perm_class_name "target_name", "action"; };Principal フィールドは、次のようになります。
Principal Principal_class "principal_name"つまり、"Principal" という語 (大文字、小文字は区別されない) に続き、完全修飾の Principal クラス名およびプリンシパル名を指定します。
Principal クラスは、java.security.Principal インタフェースを実装するクラスです。 すべての Principal オブジェクトは、
getName
メソッドの呼び出しによって取得できる関連名を持っています。 名前に使用される書式は、Principal 実装によって異なります。このチュートリアルで使用する、基本的な認証機構により作成されるサブジェクト内に配置されるプリンシパルのタイプは、
SamplePrincipal
です。これが、grant
文のプリンシパル指示部のPrincipal_class
で使用されます。SamplePrincipal
のユーザ名は name の形式になります。このチュートリアルで使用可能なユーザ名は testUser だけです。したがって、grant
文の指示部Principal_class
では testUser を使用します。単一の
grant
文内に複数の Principal フィールドを含めることも可能です。 複数の Principal フィールドを指定する場合、現行のアクセス制御コンテキストに関連付けられたサブジェクトにこれらのプリンシパルすべてが含まれる場合にのみ、grant
文のアクセス権が付与されます。複数のプリンシパルに同じアクセス権のセットを付与するには、複数の
grant
文を作成し、各文にアクセス権のリストとどちらかのプリンシパルを指し示す単一の Principal フィールドを含めます。このチュートリアルのポリシーファイルでは、Principal フィールドに 1 つの
grant
文が含まれます。grant codebase "file:./SampleAction.jar", Principal sample.principal.SamplePrincipal "testUser" { permission java.util.PropertyPermission "java.home", "read"; permission java.util.PropertyPermission "user.home", "read"; permission java.io.FilePermission "foo.txt", "read"; };これは、指定したアクセス権を、
SampleAction.jar
内のコードを実行する指定されたプリンシパルに付与することを示します。 注: SamplePrincipal クラスはsample.principal
パッケージ内にあります。サブジェクトのアクセス制御コンテキストへの関連付け
サブジェクトを作成し、現在のアクセス制御コンテキストに関連付けるには、次のようにします。
- 最初にユーザを認証する必要があります (「JAAS 認証」を参照)。
- Subject クラスの static メソッド
doAs
を呼び出し、認証された Subject および java.security.PrivilegedAction または java.security.PrivilegedExceptionAction に渡します。 PrivilegedAction と PrivilegedExceptionAction の違いについては、「特権ブロックのための API」を参照してください。doAs
メソッドは、提供されたサブジェクトを現在のアクセス制御コンテキストに関連付け、アクションからrun
メソッドを呼び出します。run
メソッド実装には、指定されたサブジェクトとして実行されるすべてのコードが含まれています。 このため、アクションは指定されたサブジェクトとして実行されます。このチュートリアルでも例を示しますが、Subject クラスの static メソッド
doAs
の代わりに、同じクラスの static メソッドdoAsPrivileged
が呼び出される場合があります。doAsPrivileged
は、doAs
に渡されるパラメータのほかに 3 番目のパラメータ AccessControlContext を必要とします。doAsPrivileged
は、doAs
のように提供された Subject を現在のアクセス制御コンテキストに関連付けるのではなく、提供されたアクセス制御コンテキストまたは空のアクセス制御コンテキスト (渡されたパラメータがnull
の場合) に関連付けます。これについては、以下で例を示します。 これらのメソッドの相違点については、『JAAS リファレンスガイド』の「doAs 対 doAsPrivileged」を参照してください。
このチュートリアルのコードは、4 つのファイルで構成されます。
- SampleAzn.java は、
Subject.doAsPrivileged
の呼び出しに必要なコードが追加されている点以外は、「JAAS 認証」チュートリアルのSampleAcn.java
アプリケーションファイルとまったく同じです。
- SampleAction.java には、SampleAction クラスが含まれます。 このクラスは、PrivilegedAction を実装し、プリンシパルベースの認証チェックで実行するすべてのコードを含む
run
メソッドを保持します。
- SampleLoginModule.java は、チュートリアルのログイン構成ファイル によって、基盤となる適切な認証を実装するクラスとして指定されます。 SampleLoginModule のユーザ認証は、ユーザによって指定された名前とパスワードが特定の値を持っていることを検証する処理です。 このクラスについては「JAAS 認証」チュートリアルで取り上げているので、ここでは詳しい説明を省略します。
- SamplePrincipal.javaは、
java.security.Principal
インタフェースを実装するサンプルクラスです。 SampleLoginModule によって使用されます。 このクラスについては「JAAS 認証」チュートリアルで取り上げているので、ここでは詳しい説明を省略します。
SampleLoginModule.java
ファイルとSamplePrincipal.java
ファイルについては「JAAS 認証」チュートリアルで取り上げているので、ここでは詳しい説明を省略します。 その他のソースファイルについては、以下のセクションを参照してください。SampleAzn.java
SampleAcn と同様に、SampleAzn クラスは LoginContext
lc
をインスタンス化し、login
メソッドを呼び出して認証を実行します。 認証に成功した場合は、LoginContext のgetSubject
メソッドを呼び出すことにより、認証されたサブジェクト (ユーザを表す SamplePrincipal を含む) を取得します。Subject mySubject = lc.getSubject();
main
メソッドは、サブジェクトに関する情報 (たとえばそのサブジェクトのプリンシパル情報) をユーザに提供したあと、Subject.doAsPrivileged
を呼び出し、以下のように、認証されたサブジェクトmySubject
、PrivilegedAction (SampleAction)、null
AccessControlContext を渡します。SampleAction クラスは、次の方法でインスタンス化されます。
PrivilegedAction action = new SampleAction();
Subject.doAsPrivileged
の呼び出しは、次の方法で行われます。Subject.doAsPrivileged(mySubject, action, null);次に、
doAsPrivileged
メソッドは、PrivilegedActionaction
(SampleAction) のrun
メソッドを呼び出して、サブジェクトmySubject
の代わりに実行される残りのコードの実行を開始します。AccessControlContext の 3 番目の引数として
doAsPrivileged
にnull
を渡すことにより、mySubject
が新しい空の AccessControlContext に関連付けられることを示します。 その結果、SampleAction の実行時のセキュリティチェックでは、mySubject
として実行される SampleAction コード自体 (またはこのコードによって呼び出されるその他のコード) のアクセス権のみが必要になります。doAsPrivileged
の呼び出し側 (およびdoAsPrivileged
が呼び出された時点で実行スタック上に存在していた呼び出し側) は、アクションが実行されている間、アクセス権を必要としません。SampleAction.java
SampleAction.java には、SampleAction クラスが含まれます。 このクラスは
java.security.PrivilegedAction
クラスを実装し、サブジェクトmySubject
として実行するすべてのコードを含むrun
メソッドを持っています。 このチュートリアルでは、3 つの操作を実行します。どの操作の場合も、あらかじめ必須アクセス権としてコードを付与しておく必要があります。 以下の操作を実行します。
java.home
システムプロパティの値を読み取り、出力する
user.home
システムプロパティの値を読み取り、出力する
- 現行のディレクトリに
foo.txt
という名前のファイルが存在するかどうかを確認する以下に、コードを示します。
package sample; import java.io.File; import java.security.PrivilegedAction; public class SampleAction implements PrivilegedAction { public Object run() { System.out.println("¥nYour java.home property value is: " + System.getProperty("java.home")); System.out.println("¥nYour user.home property value is: " + System.getProperty("user.home")); File f = new File("foo.txt"); System.out.print("¥nfoo.txt does "); if (!f.exists()) System.out.print("not "); System.out.println("exist in the current working directory."); return null; } }
このチュートリアルで使用するログイン構成ファイルを、「JAAS 認証」チュートリアルで使用するものと全く同じにできます。 このため、1 つのエントリのみを含む sample_jaas.config を使用できます。
Sample { sample.module.SampleLoginModule required debug=true; };このエントリの名前は "Sample" です。チュートリアルアプリケーション
SampleAcn
およびSampleAzn
がこのエントリを参照する際、この名前を使用します。 このエントリは、ユーザ認証に使用するログインモジュールがsample.module
パッケージ内の SampleLoginModule であること、認証が成功したと見なされるためにはこの SampleLoginModule が「成功する」必要があることを示します。 SampleLoginModule は、ユーザから提供された名前とパスワードが正しい (testUser と testPassword である) 場合にかぎり成功します。SampleLoginModule はデバッグオプションも定義します (
true
に設定可能)。 このオプションの値をtrue
に設定すると、SampleLoginModule により、認証の進捗に関する追加情報が出力されます。
この承認チュートリアルのアプリケーションは、
SampleAzn
とSampleAction
の 2 つのクラスで構成されます。 各クラスのコードにはセキュリティ関連操作が含まれるため、操作を実行するには、ポリシーファイル内に関連するアクセス権を指定する必要があります。このチュートリアルで使用するログインモジュール (
SampleLoginModule
) にも、アクセス権を必要とする操作が含まれています。これらの各クラスが必要とするアクセス権については以下で説明します。続いて、完全なポリシーファイルへのリンクを示します。
SampleAznに必要なアクセス権
SampleAzn
クラスの main メソッドは、アクセス権の必要な次の 2 つの操作を実行します。
- LoginContext の作成
- Subject クラスの
doAsPrivileged
static メソッドの呼び出しLoginContext の作成方法は、認証チュートリアルの場合とまったく同じです。このため、ターゲットの "
createLoginContext.Sample
" と同じjavax.security.auth.AuthPermission
アクセス権が必要です。Subject クラスの
doAsPrivileged
メソッドを呼び出すには、ターゲットの「doAsPrivileged
」を保持するjavax.security.auth.AuthPermission
が必要です。
SampleAzn
クラスが、SampleAzn.jar
という名前の JAR ファイルに配置されている場合を考えましょう。ポリシーファイル内の次のgrant
文を使って、これらのアクセス権をSampleAzn
コードに付与できます。grant codebase "file:./SampleAzn.jar" { permission javax.security.auth.AuthPermission "createLoginContext.Sample"; permission javax.security.auth.AuthPermission "doAsPrivileged"; };SampleAction に必要なアクセス権
SampleAction
コードは、アクセス権の必要な次の 3 つの操作を実行します。
- "java.home" システムプロパティの値の読み取り
- "user.home" システムプロパティの値の読み取り
- 現行のディレクトリに
foo.txt
という名前のファイルが存在するかどうかの確認これらの操作には、次のアクセス権が必要です。
permission java.util.PropertyPermission "java.home", "read"; permission java.util.PropertyPermission "user.home", "read"; permission java.io.FilePermission "foo.txt", "read";これらのアクセス権を
SampleAction.class
内のコードに付与する必要があります。このファイルは、SampleAction.jar
という名前の JAR ファイル内に配置されます。 ただし、このgrant
文の場合、アクセス権を「コード」だけではなく、コードを実行する特定のユーザにも付与することにより、特定のユーザへのアクセスを制限する方法を示します。このため、「プリンシパルベースのポリシーファイル文の作成方法」で説明したように、
grant
文は次のようになります。grant codebase "file:./SampleAction.jar", Principal sample.principal.SamplePrincipal "testUser" { permission java.util.PropertyPermission "java.home", "read"; permission java.util.PropertyPermission "user.home", "read"; permission java.io.FilePermission "foo.txt", "read"; };SampleLoginModule に必要なアクセス権
SampleLoginModule
コードは、アクセス権の必要な操作を 1 つ実行します。 Subject に Principal を追加するには、modifyPrincipals をターゲットとするjavax.security.auth.AuthPermission
が必要です。 grant 文は次のようになります。grant codebase "file:./SampleLM.jar" { permission javax.security.auth.AuthPermission "modifyPrincipals"; };完全なポリシーファイル
完全なポリシーファイルは、sampleazn.policy です。
JAAS 承認チュートリアルコードを実行するには、次の操作を行う必要があります。
- 次のファイルを 1 つのディレクトリ内に格納します。
- sample_jaas.config ログイン構成ファイル
- sampleazn.policy ポリシーファイル
- 最上位ディレクトリの下に sample という名前のサブディレクトリを作成し、ここに以下のファイルを格納します (注: SampleAzn および SampleAction クラスは
sample
パッケージ内にある)。
- SampleAzn.java ソースファイル
- SampleAction.java ソースファイル
- sample ディレクトリのサブディレクトリを作成し、module という名前を付けます。 ここに以下のファイルを格納します (注: SampleLoginModule クラスは
sample.module
パッケージ内にある)。
- SampleLoginModule.java ソースファイル
- sample ディレクトリのサブディレクトリをもう 1 つ作成し、principal という名前を付けます。 ここに以下のファイルを格納します (注: SamplePrincipal クラスは
sample.principal
パッケージ内にある)。
- SamplePrincipal.java ソースファイル
- 最上位のディレクトリですべてのソースファイルをコンパイルします。
コマンド全体を 1 行に入力してください。javac sample/SampleAction.java sample/SampleAzn.java sample/module/SampleLoginModule.java sample/principal/SamplePrincipal.java
SampleAzn.class
およびMyCallbackHandler.class
を含む JAR ファイルSampleAzn.jar
を作成します (注: これらのクラスのソースファイルはSampleAzn.java
内にある)。jar -cvf SampleAzn.jar sample/SampleAzn.class sample/MyCallbackHandler.classコマンド全体を 1 行に入力してください。
SampleAction.class
を含むSampleAction.jar
という名前の JAR ファイルを作成します。jar -cvf SampleAction.jar sample/SampleAction.classSampleLoginModule.class
とSamplePrincipal.class
を含む JAR ファイルを作成します。jar -cvf SampleLM.jar sample/module/SampleLoginModule.class sample/principal/SamplePrincipal.class
- 次の情報を指定して、
SampleAzn
アプリケーションを実行します。
- 適切な
-classpath
句。SampleAzn.jar
、SampleAction.jar
、およびSampleLM.jar
JAR ファイル内でクラスの検索が行われるようにします。
-Djava.security.manager
。セキュリティマネージャのインストールを指定します。
-Djava.security.policy==sampleazn.policy
。使用するポリシーファイルとしてsampleazn.policy
を指定します。
-Djava.security.auth.login.config==sample_jaas.config
。使用するログイン構成ファイルとして、sample_jaas.config
を指定します。以下に、Win32 および Unix システムの両方で使用可能なすべてのコマンドを示します。 classpath 項目の区切りとして、UNIX システムでは コロンを使用するのに対し、Win32 システムではセミコロンを使用する点だけが異なります。
以下に Win32 システムの全コマンドを示します。
java -classpath SampleAzn.jar;SampleAction.jar;SampleLM.jar -Djava.security.manager -Djava.security.policy==sampleazn.policy -Djava.security.auth.login.config==sample_jaas.config sample.SampleAzn以下に UNIX システムの全コマンドを示します。
java -classpath SampleAzn.jar:SampleAction.jar:SampleLM.jar -Djava.security.manager -Djava.security.policy==sampleazn.policy -Djava.security.auth.login.config==sample_jaas.config sample.SampleAznコマンド全体を 1 行で入力してください。 ここでは、読みやすくするために複数行に分けて表示してあります。 コマンドが長すぎる場合は、.bat ファイル (Win32) または .sh ファイル (UNIX) に記述します。このファイルを実行することで、コマンドを実行できます。
要求に応じてユーザ名 (testUser) とパスワード (testPassword) を入力すると、ログイン構成ファイルに指定された SampleLoginModule により、入力された名前とパスワードのチェックが行われます。 ログインに成功すると「Authentication succeeded!」というメッセージが表示されます。失敗した場合は「Authentication failed.」というメッセージと失敗の理由が表示されます。
認証が完了すると、プログラム (
SampleAction
内) の他の部分がユーザに代わって実行されます。このため、ユーザは適切なアクセス権をあらかじめ保持している必要があります。 ポリシーファイルsampleazn.policy
により、必要なアクセス権が付与されます。このため、java.home
およびuser.home
システムプロパティの値、およびfoo.txt
という名前のファイルが現在のディレクトリに存在するかどうかを示す文が表示されます。