Java(tm)プログラミング言語のアプリケーション環境のポリシーは、さまざまなソースを出所とするコードがどのようなアクセス権を使用できるかを指定し、さまざまなプリンシパルとして実行するもので、Policyオブジェクトによって表されます。 具体的には、Policyクラス(java.securityパッケージ内)で定義されているabstractメソッドを実装したPolicyサブクラスによって表されます。
Policyオブジェクトが使用するポリシー情報がどこに置かれるかは、Policyの実装によります。 Policyのリファレンス実装では、ポリシー情報を静的なポリシー構成ファイルから得ます。
このドキュメントでは、Policyのリファレンス実装と、それによって読み取られるポリシー・ファイルで使用する構文について説明します。 Policy Toolを使った(構文を知る必要のない)ポリシー・ファイルの作成方法の詳細は、Policy Toolのドキュメント(Solaris、LinuxまたはMac OS X用、Windows用)を参照してください。
このドキュメントでは、次の内容について説明します。
ポリシー・ファイルは、単純なテキスト・エディタ、またはグラフィカルなPolicy Toolユーティリティを使って作成できます。
デフォルトでは、システム全体のポリシー・ファイルが1つと、ユーザー・ポリシー・ファイル(オプション)が1つ存在します。
Policyのリファレンス実装は、そのgetPermissionsメソッドがはじめて呼び出されたとき、あるいは、そのrefreshメソッドが呼び出されたときに初期化されます。 初期化時には、ポリシー構成ファイル(「ポリシー・ファイルの構文」を参照)の解析が行われたあと、その情報がPolicyオブジェクトに読み込まれます。
前述したように、デフォルトでは、システム全体のポリシー・ファイルが1つと、ユーザー・ポリシー・ファイルが1つ存在します。
システム・ポリシー・ファイルは、デフォルトでは次の場所にあります。
java.home/lib/security/java.policy (Solaris, Linux, or Mac OS X) java.home\lib\security\java.policy (Windows)
ノート: java.homeは、「java.home」という名前のシステム・プロパティの値で、実行環境の格納先ディレクトリ(Java SE Development Kit (JDK)のjreディレクトリ、またはJava SE Runtime Environment (JRE)の最上位ディレクトリ)を指します。
システムのポリシー・ファイルは、システム全体にわたってコードにアクセス権を与えます。 JDKに含まれているjava.policyファイルは、標準拡張機能にすべてのアクセス権を与え、ユーザーが特権のないポートで待機したり、「os.name」プロパティや「file.separator」プロパティなどの任意のコードがセキュリティにかかわらない特定の「標準」プロパティを読み込んだりすることを許可します。
ユーザー・ポリシー・ファイルは、デフォルトでは次の場所にあります。
user.home/.java.policy (Solaris, Linux, or Mac OS X) user.home\.java.policy (Windows)
ノート: user.homeは「user.home」という名前のシステム・プロパティの値で、ユーザーのホーム・ディレクトリを指定します。
Policyが初期化されると、まずシステム・ポリシーがロードされ、次に、ロードされたシステム・ポリシーにユーザー・ポリシーが追加されます。 どちらのポリシーも存在しない場合は、組込みポリシーが使われます。 組込みポリシーは、JREとともにインストールしたjava.policyファイルと同じです。
ポリシー・ファイルの場所は、セキュリティ・プロパティ・ファイルの中で指定されています。セキュリティ・プロパティ・ファイルは、次の場所にあります。
java.home/lib/security/java.security (Solaris, Linux, or Mac OS X) java.home\lib\security\java.security (Windows)前述のように、
java.homeは実行環境の格納先ディレクトリ(JDKのjreディレクトリ、またはJREの最上位ディレクトリ)を指します。 ポリシー・ファイルの場所は、次のような形式の名前を持つプロパティの値として指定されています。
policy.url.n
nは数字です。 次に示す形式の行で、それぞれのプロパティの値を指定します。
policy.url.n=URLここで、
URLはURLの指定を表します。
たとえば、デフォルトのシステムおよびユーザー・ポリシー・ファイルは、セキュリティ・プロパティ・ファイルに次のように指定されています。
policy.url.1=file:${java.home}/lib/security/java.policy
policy.url.2=file:${user.home}/.java.policy
${java.home}を使用してjava.homeプロパティの値を指定するなど、特別な構文でプロパティの値を指定する方法については、「プロパティの展開」を参照してください。
URLをいくつも指定して(http://形式のものを含む)、該当するポリシー・ファイルをすべてロードすることもできます。 また、上に示したポリシー・ファイルの指定のうち、2番目のポリシー・ファイルの指定をコメント・アウトするか、あるいは修正すれば、デフォルト・ユーザー・ポリシー・ファイルの読込みを無効にすることができます。
アルゴリズムは、policy.url.1から処理を開始して、番号を1つずつ増やしながら、URLが見つからなくなるまで処理を続けます。 したがって、policy.url.1とpolicy.url.3がある場合、policy.url.3は読み込まれません。
アプリケーションを実行するときに、追加のポリシー・ファイルや別のポリシー・ファイルを指定することもできます。 この場合は、「-Djava.security.policy」コマンド行引数を使ってjava.security.policyプロパティの値を設定します。 たとえば、次のように指定します。
java -Djava.security.manager -Djava.security.policy=someURL SomeApp
ここでsomeURLは、ポリシー・ファイルの位置を示すURLです。指定されたポリシー・ファイルは、セキュリティ・プロパティ・ファイルで指定されたすべてのポリシー・ファイルに追加されてロードされます。
ノート:
java -Djava.security.manager -Djava.security.policy=mypolicy SomeApp
-Djava.security.manager」引数によってデフォルト・セキュリティ・マネージャがインストールされるので、このアプリケーションに対してはポリシーのチェックが行われます。 アプリケーションSomeAppがセキュリティ・マネージャをインストールする場合は、この引数は必要ありません。 次のように指定することもできます。
java -Djava.security.manager -Djava.security.policy==someURL SomeApp
等号が2つ使われていることに注意してください。この場合は、指定されたポリシー・ファイルだけが使われ、セキュリティ・プロパティに示されたポリシー・ファイルはすべて無視されます。
ポリシー・ファイルをappletviewer (アプレット・ビューア)に渡す場合は、次のように「-J-Djava.security.policy」引数を指定します。
appletviewer -J-Djava.security.policy=someURL myApplet
ノート: セキュリティ・プロパティ・ファイルでpolicy.allowSystemPropertyプロパティにfalseが設定されている場合、-Djava.security.policyのポリシー・ファイルの値は(javaコマンドとappletviewerコマンドのどちらの場合も)無視されます。 デフォルトはtrueです。
新しいポリシー・クラスを作成し、Policyのリファレンス実装クラスと置き換えることもできます。この場合は、Policy抽象クラスのサブクラスを作成し、getPermissionsメソッド(必要に応じてその他のメソッドも)を実装します。
セキュリティ・プロパティ・ファイル(JDKまたはJREのlib/securityディレクトリのjava.securityファイル)を編集すれば、Policyのリファレンス実装を変更できます。
java.securityで設定できるプロパティの例を次に示します。
policy.provider=PolicyClassName
PolicyClassNameには、目的のPolicy実装クラスを完全修飾名で指定します。 デフォルトのセキュリティ・プロパティ・ファイルでは、このプロパティは次のように指定されています。
policy.provider=sun.security.provider.PolicyFile
カスタマイズするには、次のように、このプロパティに別のクラスを指定します。
policy.provider=com.mycom.MyPolicy
インストールしたJDKまたはJREのポリシー構成ファイルでは、指定されたコード・ソースからのコードに対し、どのようなアクセス権(システム・リソースへのアクセスの種類)を与え、指定したプリンシパルとして実行するかを指定します。
アプレット(またはセキュリティ・マネージャの下で動作しているアプリケーション)が、ファイルの読み書きなど、セキュリティ保護された操作を行うためには、その操作を行うためのアクセス権が与えられている必要があります。 Policyのリファレンス実装では、ポリシー構成ファイルの付与エントリによって、そのアクセス権を与える必要があります。 詳しくは、以降の説明と「Javaセキュリティ・アーキテクチャ」を参照してください。 (ただし、同じ(URLの)場所にあるファイルと、その場所のサブディレクトリにあるファイルの読取りアクセス権は、常に自動的に与えられます。したがって、そのようなアクセス権については、明示的に指定する必要はありません。)
ポリシー構成ファイルは、エントリのリストで構成されます。 1つのkeystoreエントリと、0以上のgrantエントリを持たせることができます。
キーストアは、非公開キーと、対応する公開キーを認証するX.509証明書チェーンなどのデジタル証明書が格納されたデータベースです。 キーストアの作成と管理には、keytoolユーティリティ(Solaris、LinuxまたはMac OS X用、Windows用)を使います。 ポリシー構成ファイルで指定されているキーストアは、そのファイルのgrantエントリで指定されている署名者の公開キーを照合するために使用されます。 署名者の別名を指定しているgrantエントリがある場合、またはプリンシパルの別名を指定しているgrantエントリがある場合は、ポリシー構成ファイルに必ずkeystoreエントリを置きます(次を参照)。
このとき、ポリシー・ファイル内で有効なkeystore/keystorePasswordURLエントリは1つのみです。最初のエントリ以外の後続エントリは無視されます。 このエントリは、ファイルのgrantエントリ外部の任意の場所に配置できます。 構文は次のとおりです。
keystore "some_keystore_url", "keystore_type", "keystore_provider"; keystorePasswordURL "some_password_url";
some_keystore_urlにはキーストアのURLの場所を指定し、some_password_urlにはキーストア・パスワードのURLの場所を指定し、keystore_typeにはキーストアのタイプを指定し、keystore_providerにはキーストアのプロバイダを指定します。 some_keystore_urlからの入力ストリームはKeyStore.loadメソッドに渡されることに注意してください。 URLとしてNONEが指定されている場合は、nullのストリームがKeyStore.loadメソッドに渡されます。 NONEは、KeyStoreがファイルベースではなく、たとえば、ハードウェア・トークン・デバイスに置かれている場合に指定します。
URLは、ポリシー・ファイルがある場所からの相対位置を表します。 たとえば、セキュリティ・プロパティ・ファイルの中でポリシー・ファイルが次のように指定されているとします。
policy.url.1=http://foo.example.com/fum/some.policy
また、このポリシー・ファイルには、次のエントリがあるとします。
keystore ".keystore";
この場合、キーストアは次の場所からロードされます。
http://foo.example.com/fum/.keystore
URLに絶対位置を指定することもできます。
キーストアのタイプは、キーストア情報の格納形式とデータ形式を定義するとともに、キーストア内の非公開キーとキーストア自体の整合性を保護するために使われるアルゴリズムを定義します。 Sun Microsystemsがサポートするデフォルトのタイプは、Sun Microsystemsに所有権があるキーストア・タイプ名「JKS」です。 したがって、キーストアのタイプが「JKS」であれば、キーストア・エントリを指定する必要はありません。
実行されるコードは、常に、特定の「コード・ソース」(CodeSource型のオブジェクトによって表される)から来ると考えられます。 コード・ソースは、コードの出所を表す場所(URL)だけでなく、コードの署名に使われた非公開キーに対応する公開キーを含んだ証明書への参照も含みます。 コード・ソース内の証明書は、ユーザーのキーストアからのシンボリックな別名によって参照されます。 コードはさらに、特定のプリンシパル(Principal型のオブジェクトによって表される)またはプリンシパルのグループとして実行されると考えられます。
各付与エントリには、オプションのcodeBaseとsignedBy、およびプリンシパルの名前と値のペアのあとに、アクセス権を付与するコードを指定する1つ以上の「アクセス権エントリ」が含まれます。 付与エントリの基本形式は、次のとおりです。
grant signedBy "signer_names", codeBase "URL",
principal principal_class_name "principal_name",
principal principal_class_name "principal_name",
... {
permission permission_class_name "target_name", "action",
signedBy "signer_names";
permission permission_class_name "target_name", "action",
signedBy "signer_names";
...
};
上の形式でイタリック体になっていない項目は、示されているとおりに指定します。ただし、大文字と小文字は区別されず、また、以降で説明するように、いくつかの項目はオプションです。 イタリックで示されている項目は、可変の項目です。
付与エントリは、grantで始まります。
SignedBy、Principal、およびCodeBaseフィールドsignedBy、codeBase、およびprincipalの値はオプションです。また、これらのフィールドの順序は問われません。
signedByの値は、キーストアに格納された証明書の別名を示します。 証明書内の公開キーは、コードのデジタル署名の検証に使われます。別名によって指定されたキーストア・エントリ内の公開キーに対応する、非公開キーで署名されたコードに、アクセス権を付与します。
signedByの値には、複数の別名をカンマで区切って指定できます。 たとえば、"Adam,Eve,Charles"のように指定できます。この場合は、各要素がORではなくANDで結ばれ、「Adam、EveおよびCharlesによって署名された」という意味になります。 より厳密には、「Adamによって署名されたコード」とは、「Adamという別名が付けられたエントリを持つキーストアにある公開キー証明書に対応する、非公開キーを使って署名されたJARファイルに含まれている、クラス・ファイル内のコード」という意味です。
signedByフィールドはオプションです。省略した場合は、「任意の署名者」という意味になります。 コードに署名が付いているかどうか、だれが署名しているかは問われなくなります。
プリンシパルの値はclass_nameとprincipal_nameのペアを指定します。このペアは、実行中のスレッドのプリンシパル・セット内にある必要があります。 プリンシパル・セットは、Subjectによって実行するコードに関連付けられます。
principal_class_nameにワイルドカード値(*)を設定することで、任意のPrincipalクラスに一致させることができます。 さらに、principal_nameにワイルドカード値(*)を設定することで、任意のPrincipal名に一致させることができます。 principal_class_nameまたはprincipal_nameに*を設定するときは、*を引用符で囲まないでください。 また、ワイルドカードのプリンシパル・クラスを指定する場合は、ワイルドカードのプリンシパル名も指定する必要があります。
プリンシパル・フィールドは省略可能です。省略した場合は、「任意のプリンシパル」という意味になります。
プリンシパルclass_name/principal_nameのペアが単一引用符で囲まれた文字列として指定される場合は、キーストアの別名として扱われます。 キーストアは別名を経由してX509証明書を調査し、問い合わせます。 キーストアがある場合は、principal class_nameは自動的にjavax.security.auth.x500.X500Principalとして扱われ、principal_nameは証明書で名前を識別されたサブジェクトとして自動的に扱われます。 X509証明書のマッピングが見つからない場合は、grantエントリはすべて無視されます。
codeBaseの値は、コードが置かれる場所を示します。この場所からコードにアクセス権を付与します。 codeBaseエントリを省略した場合は、「任意のコード」という意味になり、コードの出所は問われません。
ノート: codeBaseの値はURLであるため、コード・ソースがWindowsシステム上にある場合であっても、ディレクトリの区切り文字は、バックスラッシュではなく、必ずスラッシュを使います。 したがって、Windowsシステム上でコードの場所がC:\somepath\api\の場合、codeBaseポリシー・エントリは次のように指定します。
grant codeBase "file:/C:/somepath/api/" {
...
};
codeBase値の正確な意味は、末尾の文字によって異なります。 末尾が「/」のcodeBaseは、指定されたディレクトリ内のすべてのクラス・ファイル(JARファイルを除く)を示します。 末尾が「/*」のcodeBaseは、そのディレクトリ内にあるすべてのファイル(クラス・ファイルとJARファイルの両方)を示します。 末尾が「/-」のcodeBaseは、指定されたディレクトリとその下の全サブディレクトリ内のすべてのファイル(クラス・ファイルとJARファイルの両方)を示します。 次の表では、さまざまなケースを示します。
| ダウンロードされたコードのcodebase URL | ポリシーのcodebase URL | 一致するかどうか |
|---|---|---|
| www.example.com/people/gong/ | www.example.com/people/gong | Y |
| www.example.com/people/gong/ | www.example.com/people/gong/ | Y |
| www.example.com/people/gong/ | www.example.com/people/gong/* | Y |
| www.example.com/people/gong/ | www.example.com/people/gong/- | Y |
| www.example.com/people/gong/appl.jar | www.example.com/people/gong/ | N |
| www.example.com/people/gong/appl.jar | www.example.com/people/gong/- | Y |
| www.example.com/people/gong/appl.jar | www.example.com/people/gong/* | Y |
| www.example.com/people/gong/appl.jar | www.example.com/people/- | Y |
| www.example.com/people/gong/appl.jar | www.example.com/people/* | N |
| www.example.com/people/gong/ | www.example.com/people/- | Y |
| www.example.com/people/gong/ | www.example.com/people/* | N |
アクセス権エントリは、単語permissionで始まります。 前述のテンプレートにある単語permission_class_nameは、実際にはjava.io.FilePermissionやjava.lang.RuntimePermissionなどの特定のアクセス権タイプになります。
java.io.FilePermission (どのような種類のファイル・アクセスを許可するかを指定)など、多くのアクセス権タイプでは"action"が必須です。 java.lang.RuntimePermissionなどのカテゴリでは不要なため、必須ではありません。その場合は、permission_class_nameの後の"target_name"値で指定されたアクセス権が与えられるか、アクセス権が与えられないかのどちらかになります。
アクセス権エントリのsignedByの名前と値のペアは省略可能です。 この値が存在する場合は、署名付きアクセス権であることを示します。 つまり、そのアクセス権を与えられるようにするためには、アクセス権クラスそれ自体が、指定された別名によって署名されていなければなりません。 たとえば、次のような付与エントリがあるとします。
grant {
permission Foo "foobar", signedBy "FooSoft";
};
この場合、アクセス権Foo.classがあるJARファイルに置かれていて、そのJARファイルが別名"FooSoft"により指定される証明書に含まれている公開キーに対応する非公開キーによって署名されているか、Foo.classがシステム・クラスである場合に、このアクセス権タイプFooが与えられます。システム・クラスはポリシーによる制限を受けません。
アクセス権エントリの各項目は、指定された順序(permission、permission_class_name、"target_name"、"action"、およびsignedBy "signer_names")で並んでいる必要があります。 各エントリはセミコロンで終わります。
識別子(permission、signedBy、codeBaseなど)では大文字と小文字は区別されませんが、permission_class_nameと、値として引き渡される文字列については大文字と小文字が区別されます。
ノート: java.io.FilePermissionを指定する場合、"target_name"はファイル・パスになります。 Windowsシステムでは、ファイル・パスをcodeBase URLではなく直接文字列で指定する場合は、パス中のバックスラッシュは、次のように2つ重ねて指定する必要があります。
grant {
permission java.io.FilePermission "C:\\users\\cathy\\foo.bat", "read";
};
これは、文字列はトークナイザ(java.io.StreamTokenizer)によって処理され、トークナイザは「\」をエスケープ文字列と解釈するため(たとえば、「\n」は改行を表す)、バックスラッシュそのものを表すためには、バックスラッシュを2つ重ねなければならないからです。 トークナイザは、上記のファイル・パス文字列の処理を終えると、二重のバックスラッシュを単一のバックスラッシュに変換し、最終的には次のようになります。
"C:\users\cathy\foo.bat"
ポリシー構成ファイルから取り出した2つのエントリの例を次に示します。
// If the code is signed by "Duke", grant it read/write access to all
// files in /tmp:
grant signedBy "Duke" {
permission java.io.FilePermission "/tmp/*", "read,write";
};
// Grant everyone the following permission:
grant {
permission java.util.PropertyPermission "java.vendor", "read";
};
別のポリシー構成ファイルの例を次に示します。
grant signedBy "sysadmin", codeBase "file:/home/sysadmin/*" {
permission java.security.SecurityPermission "Security.insertProvider.*";
permission java.security.SecurityPermission "Security.removeProvider.*";
permission java.security.SecurityPermission "Security.setProperty.*";
};
これは、次の条件を満たすコードだけがSecurityクラス内のメソッドを呼び出して、プロバイダの追加または削除を行なったり、Securityプロパティを設定したりできることを示しています。
/home/sysadmin/"ディレクトリにある、署名されたJARファイルからコードがロードされた。コード・ソースを指定するコンポーネントは、どちらも(または両方を)省略可能です。 codeBaseを省略した例を次に示します。
grant signedBy "sysadmin" {
permission java.security.SecurityPermission "Security.insertProvider.*";
permission java.security.SecurityPermission "Security.removeProvider.*";
};
このポリシーが有効な場合、"sysadmin"によって署名されたJARファイルに含まれるコードは、JARファイルの出所に関係なく、プロバイダの追加と削除が行えます。
署名者を省略した例を次に示します。
grant codeBase "file:/home/sysadmin/-" {
permission java.security.SecurityPermission "Security.insertProvider.*";
permission java.security.SecurityPermission "Security.removeProvider.*";
};
この場合、ローカル・ファイル・システムの"/home/sysadmin/"ディレクトリに置かれたコードは、プロバイダの追加と削除を行うことができます。 コードに署名は必要ありません。
codeBaseとsignedByを両方とも省略した例を次に示します。
grant {
permission java.security.SecurityPermission "Security.insertProvider.*";
permission java.security.SecurityPermission "Security.removeProvider.*";
};
この例では、コード・ソースを指定する要素がどちらも省略されています。したがって、出所がどこか、署名が付いているか、だれの署名が付いているかに関係なく、どのコードでもプロバイダの追加と削除が行えます。
次の例は、プリンシパルベースのエントリを表しています。
grant principal javax.security.auth.x500.X500Principal "cn=Alice" {
permission java.io.FilePermission "/home/Alice", "read, write";
};
これにより、X500Principalのアクセス権"cn=Alice"として実行するコードは"/home/Alice"を読み取ることも書き込むことも可能になります。
次の例は、ワイルドカード値を含むプリンシパルベースのエントリを表しています。
grant principal javax.security.auth.x500.X500Principal * {
permission java.io.FilePermission "/tmp", "read, write";
};
これにより、X500Principalのアクセス権(識別名に関係なく)として実行するコードは"/tmp"を読み取ることも書き込むことも可能になります。
次の例は、codesource情報とprincipal情報を持つgrant文を表しています。
grant codebase "http://www.games.example.com",
signedBy "Duke",
principal javax.security.auth.x500.X500Principal "cn=Alice" {
permission java.io.FilePermission "/tmp/games", "read, write";
};
これにより、"Duke"によって署名され、"www.games.example.com"からダウンロードされたコードが"cn=Alice"によって実行されると、"/tmp/games"ディレクトリへの読取り権と書出し権が与えられます。
次の例は、キーストアの別名を置き換えるgrant文を示しています。
keystore "http://foo.example.com/blah/.keystore";
grant principal "alice" {
permission java.io.FilePermission "/tmp/games", "read, write";
};
"alice"は次のアクセス権に置き換えられます。
javax.security.auth.x500.X500Principal "cn=Alice"
ただし、キーストアの別名aliceに関連付けられたX.509証明書がサブジェクトの識別名"cn=Alice"を持っていることが前提となります。 これにより、X500Principalのアクセス権"cn=Alice"によって実行されるコードに、"/tmp/games"ディレクトリへの読取り権と書出し権が与えられます。
プロパティの展開は、シェルでの変数の展開に似ています。 ポリシー・ファイルまたはセキュリティ・プロパティ・ファイルに次のような文字列がある場合、
${some.property}
この文字列はシステム・プロパティの値に展開されます。 たとえば、
permission java.io.FilePermission "${user.home}", "read";
この場合、"${user.home}"は、システム・プロパティ"user.home"の値に展開されます。 そのプロパティの値が"/home/cathy"である場合、上の記述は下の記述と同じになります
permission java.io.FilePermission "/home/cathy", "read";
プラットフォームにより異なるポリシー・ファイルを使いやすくするために、"${/}"という特殊な表記("${file.separator}"の簡略形)も使用できます。 この表現を使用して、次のような指定が可能です。
permission java.io.FilePermission "${user.home}${/}*", "read";
"user.home"プロパティの値が/home/cathyで、プラットフォームがSolaris、LinuxまたはMac OS Xである場合、これは次のように変換されます。
permission java.io.FilePermission "/home/cathy/*", "read";
Windowsシステムで、"user.home"の値がC:\users\cathyであれば、次のように変換されます。
permission java.io.FilePermission "C:\users\cathy\*", "read";
特殊なケースとして、コード・ベースのプロパティを次のように記述すると、
grant codeBase "file:${java.home}/lib/ext/"
file.separator文字は自動的に/に変換されます。 したがって、Windowsシステムでは次のように変換されます。
grant codeBase "file:C:/jdk1.4/jre/lib/ext/"
これは"java.home"がC:\jdk1.4\jreに設定されている場合も同様です。 したがって、コード・ベース文字列では${/}を使用する必要はありません(使用しないでください)。
プロパティの展開は、ポリシー・ファイル内で、二重引用符で囲まれた文字列が使用できる場所であればどこでも行われます。 これには、"signer_names"、"URL"、"target_name"、"action"の各フィールドが含まれます。
プロパティの展開が許可されるかどうかは、セキュリティ・プロパティ・ファイルの"policy.expandProperties"プロパティの値によって決まります。 このプロパティの値がtrue (デフォルト)の場合は、展開が許可されます。
ノート: ネストされたプロパティは使用できません。 たとえば、
"${user.${foo}}"
この例では、"foo"プロパティが"home"に設定されている場合であっても、エラーになります。 これは、プロパティ構文解析プログラムはネストされたプロパティを認識しないためです。プロパティ構文解析プログラムは、最初の「${」を見つけたら、次に最初の「}」を探し、その結果(この場合は「${user.$foo}」)をプロパティと解釈しようと試みます。しかし、そのようなプロパティがない場合はエラーになります。
ノート: 付与エントリ、アクセス権エントリ、またはキーストア・エントリで展開できないプロパティがある場合、そのエントリは無視されます。 たとえば、次のようにシステム・プロパティ"foo"が定義されていない場合、
grant codeBase "${foo}" {
permission ...;
permission ...;
};
このgrantエントリ内のpermissionはすべて無視されます。 また、次のような場合、
grant {
permission Foo "${foo}";
permission Bar "barTarget";
};
"permission Foo..."エントリだけが無視されます。 また、次のように指定されている場合、
keystore "${foo}";
この場合は、keystoreエントリが無視されます。
grant {
permission java.io.FilePermission "C:\\users\\cathy\\foo.bat", "read";
};
文字列はトークナイザ(java.io.StreamTokenizer)によって処理されますが、そこでは「\」を使用したエスケープ文字列(改行を表す「\n」など)の使用が許されるので、単一のバックスラッシュを表すためには2つの連続したバックスラッシュを使用する必要があります。 トークナイザは、上記のファイル・パス文字列の処理を終えると、二重のバックスラッシュを単一のバックスラッシュに変換し、最終的には次のようになります。
"C:\users\cathy\foo.bat"
文字列中のプロパティの展開は、トークナイザがその文字列の処理を完了したあとに行われます。 たとえば、次のような文字列があるとします。
"${user.home}\\foo.bat"
トークナイザは、この文字列中の二重のバックスラッシュを単一のバックスラッシュに変換し、結果は次のようになります。
"${user.home}\foo.bat"
次に、${user.home}プロパティが展開されて次のようになります。
"C:\users\cathy\foo.bat"
ここでは、"user.home"の値をC:\users\cathyとしています。 もちろん、プラットフォームに依存しないために、明示的にスラッシュを使うのではなく、${/}プロパティを使って次のように指定する方が望ましいと言えます。
"${user.home}${/}foo.bat"
${{protocol:protocol_data}}
このような文字列がアクセス権名に含まれる場合、protocolの値によって実行される展開のタイプが決まり、protocol_dataは展開を実行するために使用されます。protocol_dataは空にすることもできます。空の場合は、上記の文字列は次のような単純な形式になります。
${{protocol}}
デフォルトのポリシー・ファイルの実装では、次の2つのプロトコルがサポートされます。
${{self}}
プロトコルselfは、${{self}}文字列全体を1つ以上のプリンシパル・クラスとプリンシパル名のペアに置き換えることを示します。 実際に実行される置換えは、permissionを含むgrant節の内容によって決まります。
grant節にプリンシパルの情報が含まれていない場合は、permissionは無視されます。プリンシパルベースのgrant節のコンテキストでは、ターゲット名に${{self}}を含むpermissionのみが有効です。 たとえば、次のgrant節内のBarPermissionは常に無視されます。
grant codebase "www.example.com", signedby "duke" {
permission BarPermission "... ${{self}} ...";
};
grant句にプリンシパル情報が含まれている場合は、${{self}}がそのプリンシパル情報に置き換えられます。 たとえば、次のgrant句のBarPermission内の${{self}}は、javax.security.auth.x500.X500Principal "cn=Duke"に置き換えられます。
grant principal javax.security.auth.x500.X500Principal "cn=Duke" {
permission BarPermission "... ${{self}} ...";
};
grant句内にカンマで区切られたプリンシパルのリストがある場合、${{self}}は、そのカンマで区切られたプリンシパルのリストに置き換えられます。 grant句内のプリンシパル・クラスとプリンシパル名がどちらもワイルドカードになっている場合、${{self}}は、現在のAccessControlContext内のSubjectに関連付けられたすべてのプリンシパルに置き換えられます。
次の例は、selfとキーストアの別名の置き換えの両方を含む例を示しています。
keystore "http://foo.example.com/blah/.keystore";
grant principal "duke" {
permission BarPermission "... ${{self}} ...";
};
上の例では、最初に"duke"がjavax.security.auth.x500.X500Principal "cn=Duke"に展開されます。ただし、キーストアの別名"duke"に関連付けられたX.509証明書がサブジェクトの識別名"cn=Duke"を持っていることが前提となります。 次に、${{self}}が、grant節内で展開されたその同じプリンシパル情報に置き換えられます。javax.security.auth.x500.X500Principal "cn=Duke" ${{alias:alias_name}}
プロトコルaliasは、java.security.KeyStore別名の置換を示します。 KeyStoreエントリに指定されたKeyStoreが使用されます。alias_nameは、KeyStoreの別名を表します。${{alias:alias_name}}は、javax.security.auth.x500.X500Principal "DN"に置き換えられます。DNは、alias_nameに属する証明書のサブジェクトの識別名を表します。たとえば、 たとえば、
keystore "http://foo.example.com/blah/.keystore";
grant codebase "www.example.com" {
permission BarPermission "... ${{alias:duke}} ...";
};
上の例の別名dukeに関連付けられているX.509証明書は、キーストア foo.example.com/blah/.keystoreから取得されます。 dukeの証明書がサブジェクト識別名として"o=dukeOrg, cn=duke"を指定し、${{alias:duke}}がjavax.security.auth.x500.X500Principal "o=dukeOrg, cn=duke"で置き換えられるものとします。
次のエラー条件に該当する場合、アクセス権エントリは無視されます。
alias_nameが指定されていないalias_nameの証明書を取得できない