3 アクセス権とセキュリティーポリシー


3.1 Permission クラス

Permission クラスは、システムリソースへのアクセス権を表します。java.security.Permission クラスは抽象クラスで、このクラスから、特定のアクセス権を表すサブクラスが作られます。

アクセス権の例としては、次のコードを使うと /tmp ディレクトリの「abc」というファイルの読み取りアクセス権が得られます。

    perm = new java.io.FilePermission("/tmp/abc", "read");
新しいアクセス権は、Permission クラス、またはそのサブクラスの 1 つ (java.security.BasicPermission など) からサブクラス化されます。サブクラス化された、BasicPermission 以外のアクセス権は通常、それ自体のパッケージに属します。したがって、FilePermission は java.io パッケージにあります。

すべての新規 Permission クラスに実装する必要のある重要な抽象メソッドが、implies メソッドです。基本的に、「a implies b」は、アクセス権「a」を与えられている者は、当然アクセス権「b」を与えられるということを意味します。この点は、アクセス制御の決定の際に重要です。

抽象クラス java.security.Permission には、java.security.PermissionCollection という名前の抽象クラスと java.security.Permissions という final クラスが関連します。

java.security.PermissionCollection クラスは、ファイルのアクセス権など 1 つのカテゴリの Permission オブジェクトのコレクション (複製可能なセット) を表し、簡単にグループ化できるようになっています。ファイルのアクセス権などのように、アクセス権を PermissionCollection オブジェクトに任意の順序で追加できる場合は、implies 関数が呼び出されたときに、PermissionCollection オブジェクトが確実に正しいセマンティクスに従うことが重要です。

java.security.Permissions クラスは、Permission オブジェクトのコレクションを表します。つまり、異種のアクセス権のスーパーコレクションです。

アプリケーションには、システムがサポートしているアクセス権の新規のカテゴリを自由に追加できます。アプリケーションに特定のアクセス権を追加する方法については、あとで説明します。

以降では、すべての組み込みアクセス権の構文とセマンティクスについて説明します。


3.1.1 java.security.Permission

この abstract クラスは、すべてのアクセス権の上位クラスです。すべてのアクセス権に必要な必須機能を定義します。

アクセス権の各インスタンスは、通常、コンストラクタに 1 つ以上の文字列パラメータを渡すことによって生成されます。2 つのパラメータを使う一般的なケースでは、通常、1 つ目のパラメータは「ターゲットの名前」 (アクセス権の目的のファイル名など) で、2 つ目のパラメータは動作 (ファイルに対する「読み取り」動作など) です。通常、複数の動作のセットをコンマで区切った文字列の組み合わせで指定できます。


3.1.2 java.security.PermissionCollection

このクラスは、同一種のアクセス権のコレクションを持ちます。つまり、このクラスの各インスタンスは、同じタイプのアクセス権だけを持ちます。

3.1.3 java.security.Permissions

このクラスは、異種のアクセス権のコレクションのために設計されています。基本的に、このクラスは java.security.PermissionCollection オブジェクトのコレクションです。

3.1.4 java.security.UnresolvedPermission

前述したように、セキュリティーポリシーの内部状態は通常、各コードソースに関連するアクセス権オブジェクトによって表されます。しかし、Java テクノロジの動的な性質を考慮すると、ポリシーが初期化された時点で、特定のアクセス権クラスを実装した実際のコードがまだロードされておらず、Java アプリケーション環境に定義されていない可能性があります。たとえば、参照されたアクセス権クラスは、あとにロードされる JAR ファイル内にある可能性があります。

UnresolvedPermission クラスは、こうした「未解決」のアクセス権を保持するために使用されます。同様に、java.security.UnresolvedPermissionCollection クラスには UnresolvedPermission アクセス権のコレクションが保存されます。

アクセス制御の際に、以前は未解決であったものの、現在そのクラスがロードされているアクセス権のタイプがチェックされ、未解決のアクセス権が「解決」されて、適切なアクセス制御が決定されます。つまり、可能であれば、UnresolvedPermission 内の情報に基づいて適切なクラスタイプの新規オブジェクトのインスタンスが生成されます。この新規オブジェクトが UnresolvedPermission に置き換わり、UnresolvedPermission は削除されます。

この時点でも解決されないアクセス権は、セキュリティーポリシーで付与されない無効なアクセス権とみなされます。


3.1.5 java.io.FilePermission

このクラスのターゲットは、次のように指定されます。ここで、ディレクトリとファイルの名前は文字列で、空白文字を含むことはできません。
file
directory (same as directory/)
directory/file
directory/* (all files in this directory)
* (all files in the current directory)
directory/- (all files in the file system under this directory)
- (all files in the file system under the current directory)
"<<ALL FILES>>" (all files in the file system)
「<<ALL FILES>>」は特別な文字列で、システム内のすべてのファイルを表します。UNIX システムでは、root ディレクトリの下のすべてのファイルです。MS-DOS システムでは、すべてのドライブのすべてのファイルです。

動作は、readwritedelete、および execute です。ファイルのアクセス権を作成する有効なコード例を次に示します。

import java.io.FilePermission;

FilePermission p = new FilePermission("myfile", "read,write");
FilePermission p = new FilePermission("/home/gong/", "read");
FilePermission p = new FilePermission("/tmp/mytmp", "read,delete");
FilePermission p = new FilePermission("/bin/*", "execute");
FilePermission p = new FilePermission("*", "read");
FilePermission p = new FilePermission("/-", "read,execute");
FilePermission p = new FilePermission("-", "read,execute");
FilePermission p = new FilePermission("<<ALL FILES>>", "read");
> このクラスの implies メソッドは、ファイルシステムを正確に解釈します。たとえば、FilePermission("/-", "read,execute") は、FilePermission("/home/gong/public_html/index.html", "read") を表し、FilePermission("bin/*", "execute") は FilePermission("bin/emacs19.31", "execute") を表します。

注:多くの場合、これらの文字列の形式はプラットフォームにより異なります。たとえば、Windows システムの C ドライブ上の temp ディレクトリの foo というファイルへの読み取りアクセスを表すには、次の表現を使用します。

FilePermission p = new FilePermission("c:\\temp\\foo", "read");
文字列はトークナイザ (java.io.StreamTokenizer) によって処理されますが、そこでは「\」を使ったエスケープ文字列 (改行を表す「\n」など) が許されるので、単一のバックスラッシュを表すためには二重のバックスラッシュを使う必要があります。トークナイザが FilePermission のターゲット文字列の処理を終え、二重のバックスラッシュを単一のバックスラッシュに変換すると、結果は次の実際のパスになります
"c:\temp\foo"
全プラットフォーム共通のファイル記述言語ができるまでは、文字列はプラットフォームごとに異なる形式で指定する必要があります。また、「*」や「-」のようなメタシンボルを使用して特定のファイル名を表すことはできません。これは、さしあたり許容できる程度の小さな制限事項だと考えます。UNIX システムでは「/-」と「<<ALL FILES>>」は、どちらもファイルシステム全体を指します。(利用可能なファイルシステムであれば、複数のファイルシステムを指すこともできる。) 別のオペレーティングシステム (MS Windows や MacOS など) ではこの 2 つは、別のターゲットを指す可能性があります。

次のように、ターゲットがディレクトリだけで動作が「read」の場合は、

FilePermission p = new FilePermission("/home/gong/", "read");
そのディレクトリ内のファイルを一覧表示するためだけのアクセス権が与えられ、ファイルの読み取りは許可されません。ファイルの読み取りを許可するには、次のように明示的なファイル名を指定するか、「*」または「-」を指定します。
FilePermission p = new FilePermission("/home/gong/myfile", "read");
FilePermission p = new FilePermission("/home/gong/*", "read");
FilePermission p = new FilePermission("/home/gong/-", "read");
コードは必ず、そのコードと同じ (URL の) 位置、およびそのサブディレクトリの位置からのファイルの読み取りアクセス権を自動的に取得します。そのための明示的なアクセス権は必要ありません。

3.1.6 java.net.SocketPermission

このクラスは、ソケットを通じたネットワークへのアクセス権を表します。このクラスのターゲットは「hostname:port_range」の形式で指定します。hostname は次の形式で指定します。
hostname (a single host)
IP address (a single host)
localhost (the local machine)
"" (equivalent to "localhost")
hostname.domain (a single host within the domain)
hostname.subdomain.domain
*.domain (all hosts in the domain)
*.subdomain.domain
* (all hosts)
つまり、ホストは、DNS 名、数値の IP アドレス、「localhost」 (ローカルマシンの場合)、(「localhost」を指定するのと同じ) のどれかで表現されます。

DNS 名によるホストの指定では、ワイルドカード「*」を 1 つだけ使うことができます。これを使う場合は、「*.sun.com」のようにいちばん左の位置に使います。

port_range は次の形式で指定します。

N (a single port)
N- (all ports numbered N and above)
-N (all ports numbered N and below)
N1-N2 (all ports between N1 and N2, inclusive)
上の形式で、N、N1、N2 は、0 から 65535 (2^16-1) の範囲内の負でない整数です。

ソケットでの動作は、acceptconnectlisten、および resolve です (resolve は基本的に DNS の照合)。「resolve」動作は、「accept」、「connect」、および「listen」により暗示されます。つまり、ホストからの入力接続の listen や accept、またはホストへの出力接続の開始が可能なユーザーは、そのリモートホストの名前を照合できるようになるはずということです。

次に、ソケットアクセス権の例を示します。

import java.net.SocketPermission;

SocketPermission p = new SocketPermission("java.example.com","accept");
p = new SocketPermission("192.0.2.99","accept");
p = new SocketPermission("*.com","connect");
p = new SocketPermission("*.example.com:80","accept");
p = new SocketPermission("*.example.com:-1023","accept");
p = new SocketPermission("*.example.com:1024-","connect");
p = new SocketPermission("java.example.com:8000-9000",
         "connect,accept");
p = new SocketPermission("localhost:1024-",
          "accept,connect,listen");
SocketPermission("java.example.com:80,8080","accept") と SocketPermission("java.example.com,javasun.example.com","accept") は、有効なソケットアクセス権ではありません。

listen 動作はローカルホストのポートだけに適用され、accept 動作はローカルホストとリモートホストの両方のポートに適用されます。両方の動作が必要です。


3.1.7 java.security.BasicPermission

BasicPermission クラスは Permission クラスを継承します。BasicPermission と同じ命名規約に従おうとするアクセス権クラスの基底クラスとして使用できます。

BasicPermission の名前は、「exitVM」、「setFactory」、「print.queuePrintJob」など、指定したアクセス権の名前です。命名規約は、階層的なプロパティー命名規約に従います。名前の末尾には「*」や「.*」を付けて、ワイルドカードを指定できます。たとえば、「java.*」や「*」は有効ですが、「*java」や「a*b」は無効です。

動作の文字列 (Permission から継承される) は使用されません。したがって、「名前付き」のアクセス権 (名前を持つが動作リストのないアクセス権。名前付きアクセス権は、ある場合とない場合がある) の基底クラスとして、一般に BasicPermission が使用されます。必要に応じて、サブクラスは BasicPermission の上に重ねて動作を実装できます。

BasicPermission サブクラスには、java.lang.RuntimePermission、java.security.SecurityPermission、java.util.PropertyPermission、java.net.NetPermission などがあります。


3.1.8 java.util.PropertyPermission

このクラスのターゲットは、基本的には、さまざまなプロパティーファイルのセットとしての Java プロパティーの名前です。たとえば、「java.home」、「os.name」プロパティーがあります。ターゲットは、「*」 (任意のプロパティー)、「a.*」 (「a.」接頭辞を持つ名前の任意のプロパティー)、「a.b.*」などの形式で指定できます。ワイルドカードは、右端に 1 回だけ使用できます。

このクラスは、BasicPermission の上に重ねて動作を実装する BasicPermission サブクラスの 1 つです。動作は、read と write です。それぞれの意味は、次のように定義されます。「read」アクセス権は、java.lang.System 内の getProperty メソッドを呼び出してプロパティー値を取得することを許可します。「write」アクセス権は、setProperty メソッドを呼び出してプロパティー値を設定することを許可します。


3.1.9 java.lang.RuntimePermission

RuntimePermission のターゲットは任意の文字列で表現でき、このターゲットに関連する動作はありません。たとえば、RuntimePermission("exitVM") は Java 仮想マシンを終了するアクセス権を表します。

次のターゲット名を使用できます。

createClassLoader
getClassLoader
setContextClassLoader
setSecurityManager
createSecurityManager
exitVM
setFactory
setIO
modifyThread
stopThread
modifyThreadGroup
getProtectionDomain
readFileDescriptor
writeFileDescriptor
loadLibrary.{library name}
accessClassInPackage.{package name}
defineClassInPackage.{package name}
accessDeclaredMembers.{class name}
queuePrintJob

3.1.10 java.awt.AWTPermission

このクラスは、RuntimePermission と同じ考え方に基づいており、アクセス権には動作がありません。このクラスのターゲットには、次のようなものがあります。
accessClipboard
accessEventQueue
listenToAllAWTEvents
showWindowWithoutWarningBanner

3.1.11 java.net.NetPermission

このクラスには次のターゲットがあり、動作はありません。
requestPasswordAuthentication
setDefaultAuthenticator
specifyStreamHandler

3.1.12 java.lang.reflect.ReflectPermission

リフレクト操作のためのアクセス権クラスです。ReflectPermission は、名前付きのアクセス権 (RuntimePermission と同様) で、動作はありません。現在定義されている名前は、次の 1 つだけです。
suppressAccessChecks
これは、リフレクトされたオブジェクトが使用される位置で実行される、Java プログラミング言語の標準のアクセスチェック (public、default(package) アクセス、protected、private メンバーに対するチェック) を無効にします。

3.1.13 java.io.SerializablePermission

このクラスには次のターゲットがあり、動作はありません。
enableSubclassImplementation
enableSubstitution

3.1.14 java.security.SecurityPermission

SecurityPermissions は、セキュリティー関連のオブジェクト (Security、Policy、Provider、Signer、Identity オブジェクトなど) へのアクセスを管理します。このクラスには次のターゲットがあり、動作はありません。
getPolicy
setPolicy
getProperty.{key}
setProperty.{key}
insertProvider.{provider name}
removeProvider.{provider name}
setSystemScope
setIdentityPublicKey
setIdentityInfo
printIdentity
addIdentityCertificate
removeIdentityCertificate
clearProviderProperties.{provider name}
putProviderProperty.{provider name}
removeProviderProperty.{provider name}
getSignerPrivateKey
setSignerKeyPair

3.1.15 java.security.AllPermission

このアクセス権では、すべてのアクセスが許可されます。すべての (つまり多数の) アクセスの許可が必要なタスクを行うシステム管理者の仕事を簡単にするために用意されています。セキュリティーポリシーにすべてのアクセス権を繰り返し定義するのは効率的ではありません。AllPermission は、将来定義される新しいアクセス権も許可します。

このアクセス権を与える場合は、十分な注意が必要です。


3.1.16 javax.security.auth.AuthPermsision

AuthPermission では、認証アクセス権と認証に関連するオブジェクト (Subject、SubjectDomainCombiner、LoginContext、および Configuration) を扱います。このクラスには次のターゲットがあり、動作はありません。
doAs
doAsPrivileged
getSubject
getSubjectFromDomainCombiner
setReadOnly
modifyPrincipals
modifyPublicCredentials
modifyPrivateCredentials
refreshCredential
destroyCredential
createLoginContext.{name}
getLoginConfiguration
setLoginConfiguration
refreshLoginConfiguration

3.1.17 アクセス権の意味

前述したように、アクセス権は互いに比較されることがあります。このような比較を簡単に行えるように、各アクセス権クラスで implies メソッドを定義して、特定のアクセス権クラスとほかのアクセス権クラスとの関係を表す必要があります。たとえば、java.io.FilePermission("/tmp/*", "read") には java.io.FilePermission("/tmp/a.txt", "read") が含まれますが、java.net.NetPermission にはどれも含まれません。

一見しただけではわからない、暗黙の包含関係もあります。たとえば、あるアプレットにファイルシステム全体への書き込みアクセス権を与えるとします。これにより、このアプレットには、JVM 実行時環境を含むシステムのバイナリファイルの書き換えが許可されると考えられます。これは結果的に、そのアプレットにすべてのアクセス権を与えることを意味します。

別の例として、あるアプレットにクラスローダーを生成する実行時アクセス権を与える場合、クラスローダーはクリティカルな操作を実行できるので、結果的に、このアプレットにさらに多くのアクセス権を与えることになります。

「危険」を伴うアクセス権にはこれ以外に、システムプロパティーの設定を許可するもの、パッケージの定義やネイティブコードライブラリのローディングのための実行時アクセス権 (Java のセキュリティー構造はネイティブコードレベルでの悪意のある動作を防ぐように設計されていないため)、および AllPermission があります。

アクセス権の詳細については、Permissions in JDK 7 を参照してください。アクセス権を必要とする Java の組み込みメソッド、および特定のアクセス権の割り当てに伴う危険性について、一覧で説明されています。


3.1.18 新しいタイプのアクセス権を作成する方法

新機能の追加または java.lang.RuntimePermission などのクラスへの追加のターゲットキーワードの導入により、Java 2 SDK に組み込まれているアクセス権を拡張することは、Sun Microsystems だけに許されています。これは一貫性を維持するために必要なことです。

新しくアクセス権を作成するには、次の例のような方法をお勧めします。ABC 社のアプリケーション開発者が「TV を見る」ための新しいカスタムのアクセス権を作成するとします。

最初に、抽象クラス java.security.Permission (またはそのサブクラスのひとつ) を継承する新しいクラス com.abc.Permission、および com.abc.Permission を継承する新しいクラス com.abc.TVPermission を作成します。ほかのクラスの implies メソッドが正しく実装されるように注意してください。ただし、com.abc.TVPermission は中間の com.abc.Permission がなくても、直接 java.security.Permission を継承することはできます。

public class com.abc.Permission extends java.security.Permission

public class com.abc.TVPermission extends com.abc.Permission
次の図では、サブクラスの関係を示します。

Permission からサブクラス com.abc.Permission、com.abc.TVPermission への論理フローを示したフローチャート

次に、アプリケーションパッケージにそれらの新規クラスをインクルードします。

特定のコードにこの新しいタイプのアクセス権を許可する場合、各ユーザーはポリシーファイルにエントリを追加します。(ポリシーファイルの構文の詳細についてはあとのセクションで説明。) 次に、5 チャンネルを見る (watch) アクセス権を http://www.example.com/ のコードに付与するポリシーファイルの例を示します。

grant codeBase  "http://www.example.com/" {
    permission com.abc.TVPermission "channel-5", "watch";
    }
アプリケーションのリソース管理コードで、アクセス権を与えるべきかどうかのチェックを行うときは、com.abc.TVPermission オブジェクトをパラメータとして AccessController の checkPermission メソッドを呼び出します。
   com.abc.TVPermission tvperm = new
        com.abc.TVPermission("channel-5", "watch");
   AccessController.checkPermission(tvperm);
新しいアクセス権を追加するときは、新しい (アクセス権) クラスを作成します。セキュリティーマネージャーに新しいメソッドを追加するのではないので注意してください。以前は、新しいタイプのアクセスをチェックするためには SecurityManager クラスに新しいメソッドを追加する必要がありました。

「channel-1:13」や「channel-*」など、より難解な TVPermissions を許可するには、これらの擬似名のセマンティクスの扱いを知っている TVPermissionCollection オブジェクトを実装する必要があるかもしれません。

新しいコードがアクセス制御の組み込みアルゴリズムを実行するためには、AccessController クラスの checkPermission メソッドを呼び出してアクセス権チェックを起動します。ClassLoader や SecurityManager があるかどうかについては、必ずしも調べる必要はありません。ただし、インストールされているセキュリティーマネージャークラスにそのアルゴリズムを任せる場合は、SecurityManager.checkPermission メソッドを呼び出します。


3.2 java.security.CodeSource

このクラスは、HTML のコードベースの概念を拡張して、コードの位置 (URL) だけでなくその位置からの署名付きコードの確認に使用する公開鍵を持つ証明書が入ります。ただし、これは HTML ファイルの CodeBase タグと同じではないので注意してください。各証明書は java.security.cert.Certificate として表され、各 URL は java.net.URL として表されます。

3.3 java.security.Policy

どのソースからのコードにどのアクセス権が使用できるかを指定する Java アプリケーション環境のシステムセキュリティーポリシーは、Policy オブジェクトで表されます。正確には、Policy クラスの abstract メソッドを実装した Policy サブクラスにより表現されます。

ファイルの読み書きなど、アプレット (または SecurityManager の下で実行中のアプリケーション) がセキュリティーの対象である動作を行うためには、そのアプレット (またはアプリケーション) はその動作のためのアクセス権を与えられていることが必要です。唯一の例外として、コードは必ず、同じ CodeSouce、およびその CodeSouce のサブディレクトリからのファイルの読み取りアクセス権を自動的に持ちます。この場合は、明示的なアクセス権は必要ありません。

Policy オブジェクトのインスタンスは、複数存在できますが、「有効な」インスタンスは常に 1 つだけです。現在インストールされている Policy オブジェクトは getPolicy メソッドの呼び出しにより取得でき、(Policy のリセット権を持つコードによる) setPolicy メソッドの呼び出しによって変更できます。

Policy オブジェクトが使用するポリシー情報がどこに置かれるかは、Policy の実装によります。たとえば、ポリシーの構成は、単純な ASCII ファイル、Policy クラスの直列化バイナリファイル、データベースのどれかの形で保存できます。Policy のリファレンス実装の 1 つでは、情報を静的なポリシー構成ファイルから取得します。


3.3.1 Policy のファイル形式

Policy のリファレンス実装では、1 つまたは複数のポリシー構成ファイルからポリシーを指定できます。構成ファイルは、特定のコードソースからのコードに許可されるアクセス権を示します。各構成ファイルは、UTF-8 方式でエンコードする必要があります。

ポリシー構成ファイルは、エントリのリストで構成されます。1 つの keystore エントリと、0 以上の grant エントリを持たせることができます。

「キーストア」は、非公開鍵と、対応する公開鍵を認証する X.509 証明書チェーンなどのデジタル証明書が格納されたデータベースです。キーストアの作成と管理には、keytool ユーティリティーを使います。ポリシー構成ファイルで指定されているキーストアは、そのファイルの grant エントリで指定されている署名者の公開鍵を照合するために使用されます。署名者の別名を指定している grant エントリがある場合、またはプリンシパルの別名を指定している grant エントリがある場合は、ポリシー構成ファイルには必ず keystore エントリを置きます (次を参照)。

現在、ポリシーファイルで指定できる keystore エントリは 1 つだけで、2 つ目以降の keystore エントリは無視されます。keystore エントリは、ポリシーファイルの grant エントリの外であれば、どこに指定してもかまいません。keystore エントリの構文は次のとおりです。

keystore "some_keystore_url", "keystore_type";
ここで、「some_keystore_url」にはキーストアの URL 位置を指定し、「keystore_type」にはキーストアのタイプを指定します。keystore_type の指定は任意で行います。指定しない場合、キーストアのタイプは、セキュリティープロパティーファイルの「keystore.type」プロパティーで指定されたものとみなされます。

URL は、ポリシーファイルがある場所からの相対位置を表します。たとえば、セキュリティープロパティーファイルの中でポリシーファイルが次のように指定されているとします。

policy.url.1=http://foo.bar.example.com/blah/some.policy
また、このポリシーファイルには、次のエントリがあるとします。
keystore ".keystore";
この場合、キーストアは次の場所からロードされます。
http://foo.bar.example.com/blah/.keystore
URL に絶対位置を指定することもできます。

キーストアの型は、キーストア情報の格納形式とデータ形式を定義するとともに、キーストア内の非公開鍵とキーストア自体の整合性を保護するために使われるアルゴリズムを定義します。Sun Microsystems がサポートするデフォルトのタイプは、Sun Microsystems に所有権があるキーストアタイプ名「JKS」です。

ポリシーファイルの各 grant エントリは、本質的には 1 つの CodeSource とそのアクセス権から成ります。実際には、CodeSource は 1 つの URL と証明書のセットから成りますが、ポリシーファイルのエントリの内容は URL と署名者名のリストです。システムは、指定された署名者の証明書を決定するためにキーストアを調べたあとで、対応する CodeSource を生成します。

ポリシーファイルの各 grant エントリは、次の形式のどれかです。ここで先頭の「grant」は予約語で、新しいエントリの開始を示し、括弧の中にはオプション項目が示されます。各エントリ内の先頭の「permission」も予約語で、そのエントリ内で新しいアクセス権の記述が開始されることを示します。各 grant エントリは、指定したコードソースとプリンシパルに 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 ...
};
コンマの直前または直後には、空白文字を入れてもかまいません。アクセス権クラスの名前は、Java の完全修飾形のクラス名 (java.io.FilePermission など) でなければならず、省略 (FilePermission など) はできません。

動作のフィールドは、省略可能なオプションフィールドで、アクセス権クラスが動作を必要としない場合には省略できます。このフィールドを指定する場合は、必ずターゲットフィールドの直後に置きます。

CodeBase URL の正確な意味は、最後の文字に依存します。末尾が「/」の CodeBase は、指定されたディレクトリ内のすべてのクラスファイル (JAR ファイルを除く) を示します。末尾が「/*」の CodeBase は、そのディレクトリ内にあるすべてのファイル (クラスファイルと JAR ファイルの両方) を示します。末尾が「/-」の CodeBase は、指定されたディレクトリとその下の全サブディレクトリ内のすべてのファイル (クラスファイルと JAR ファイルの両方) を示します。

CodeBase フィールド (URL) は、省略可能なオプションフィールドで、省略した場合は「任意のコードベース」が指定されます。

最初の署名者名フィールドは、署名者に関連付けられている 1 組の公開鍵 (キーストアの証明書内にある) に、別のメカニズムを通じてマッピングされた文字列の別名です。これらの鍵は、ある署名付きのクラスが本当にこれらの署名者によって署名されたかどうかを確認するために使用されます。

この署名者フィールドは、複数の署名者の名前をコンマ区切りの文字列で指定できます。たとえば、「Adam,Eve,Charles」は、Adam と Eve と Charles によって署名されることを意味します (各者の関係は OR ではなく AND)。

このフィールドは省略可能なオプションフィールドで、省略した場合は「任意の署名者」、つまり「コードが署名付きかどうかは不問」の指定になります。

Permission エントリ内にある 2 つ目の署名者フィールドは、keystore エントリの別名を表します。この keystore エントリには、そのアクセス権クラスを実装しているバイトコードへの署名に使用される非公開鍵に対応する公開鍵が含まれます。このアクセス権エントリが有効なのは (つまりこのエントリに基づいてアクセス制御権が与えられるのは)、バイトコードの実装が別名によって正しく署名されていることが確認された場合だけです。

プリンシパルの値は class_name と principal_name のペアを指定します。このペアは、実行中のスレッドのプリンシパルセット内にある必要があります。プリンシパルセットは、Subject によって実行するコードに関連付けられます。プリンシパルフィールドは省略可能です。省略した場合は、「任意のプリンシパル」という意味になります。

キーストアの別名の置き換えに関するメモ:

プリンシパル class_name/principal_name のペアが単一引用符で囲まれた文字列として指定される場合は、キーストアの別名として扱われます。キーストアは別名を経由して X509 証明書を調査し、問い合わせます。キーストアがある場合は、principal_class は自動的に javax.security.auth.x500.X500Principal として扱われ、principal_name は証明書で名前を識別されたサブジェクトとして自動的に扱われます。X509 証明書のマッピングが見つからない場合は、grant エントリはすべて無視されます。

CodeBase フィールド、SignedBy フィールド、および Principal フィールドの順序は任意です。

Policy ファイル形式の、非公式の BNF 文法の例を次に示します。ここで小文字で始まる語はターミナル語です。

PolicyFile -> PolicyEntry | PolicyEntry; PolicyFile
PolicyEntry -> grant {PermissionEntry}; |
           grant SignerEntry {PermissionEntry} |
           grant CodebaseEntry {PermissionEntry} |
           grant PrincipalEntry {PermissionEntry} |
           grant SignerEntry, CodebaseEntry {PermissionEntry} |
           grant CodebaseEntry, SignerEntry {PermissionEntry} |
           grant SignerEntry, PrincipalEntry {PermissionEntry} |
           grant PrincipalEntry, SignerEntry {PermissionEntry} |
           grant CodebaseEntry, PrincipalEntry {PermissionEntry} |
           grant PrincipalEntry, CodebaseEntry {PermissionEntry} |
           grant SignerEntry, CodebaseEntry, PrincipalEntry {PermissionEntry} |
           grant CodebaseEntry, SignerEntry, PrincipalEntry {PermissionEntry} |
           grant SignerEntry, PrincipalEntry, CodebaseEntry {PermissionEntry} |
           grant CodebaseEntry, PrincipalEntry, SignerEntry {PermissionEntry} |
           grant PrincipalEntry, CodebaseEntry, SignerEntry {PermissionEntry} |
           grant PrincipalEntry, SignerEntry, CodebaseEntry {PermissionEntry} |
           keystore "url"
SignerEntry -> signedby (a comma-separated list of strings)
CodebaseEntry -> codebase (a string representation of a URL)
PrincipalEntry -> OnePrincipal | OnePrincipal, PrincipalEntry
OnePrincipal -> principal [ principal_class_name ] "principal_name" (a principal)
PermissionEntry -> OnePermission | OnePermission PermissionEntry
OnePermission -> permission permission_class_name
                 [ "target_name" ] [, "action_list"]
                 [, SignerEntry];

ここで、いくつか例を示します。次のポリシーでは、Roland によって署名されたコードにアクセス権 a.b.Foo を与えます。
grant signedBy "Roland" {
    permission a.b.Foo;
};
次の例では、すべてのコード (署名者やコードベースにかかわらず) に FilePermission を与えます。
grant {
   permission java.io.FilePermission ".tmp", "read";
};
次の例では、Li と Roland の両者によって署名されたコードに、2 つのアクセス権を与えます。
grant signedBy "Roland,Li" {
  permission java.io.FilePermission "/tmp/*", "read";
  permission java.util.PropertyPermission "user.*";
};
次の例では、Li によって署名され http://www.example.com からロードされたコードに、2 つのアクセス権を与えます。
grant codeBase "http://www.example.com/*", signedBy "Li" {
    permission java.io.FilePermission "/tmp/*", "read";
    permission java.io.SocketPermission "*", "connect";
};
次の例では、com.abc.TVPermission を実装したバイトコードが確実に Li によって署名されている場合にだけ、Li と Roland の両者によって署名されたコードに 2 つのアクセス権を与えます。
grant signedBy "Roland,Li" {
  permission java.io.FilePermission "/tmp/*", "read";
  permission com.abc.TVPermission "channel-5", "watch", 
     signedBy "Li";
};
2 つ目の署名者フィールドを使う目的は、インストールされた Java Runtime にそのアクセス権クラスが存在しない場合に、不正行為を防ぐことです。たとえば、com.abc.TVPermission クラスのコピーは、リモートの JAR アーカイブの一部としてダウンロードできますが、ユーザーポリシーにそれを参照するエントリが含まれることがあります。アーカイブは短命なので、com.abc.TVPermission クラスが別の Web サイトからふたたびダウンロードされる可能性があります。このときのユーザーポリシー内のアクセス権エントリの存在は、クラスのバイトコードの最初のコピーに対するユーザーの信頼を反映するものであるため、2 つ目のコピーが認証済みであることは重要です。

認証を確実なものにするために、バイトコードの最初のコピー (のハッシュ値) を保存して 2 つ目のコピーと比べる方法ではなく、デジタル署名を使用する理由は、アクセス権クラスの作者が合法的にクラスファイルを更新して新しい設計や実装を反映することがあるからです。

注: ファイルパスの文字列は、プラットフォームごとに異なる形式で指定する必要があります。これは、将来、全プラットフォームに共通するファイル記述言語ができるまでは必要です。上記の各例は、Solaris システム用の文字列で記述されています。Windows システムでは、文字列中で直接ファイルパスを指定する場合は、単一のバックスラッシュは次のように二重のバックスラッシュで表します。

grant signedBy "Roland" {
  permission java.io.FilePermission "C:\\users\\Cathy\\*", "read";
};
文字列はトークナイザ (java.io.StreamTokenizer) によって処理されますが、そこでは「\」を使用したエスケープ文字列 (改行を表す「\n」など) の使用が許されるので、単一のバックスラッシュを表すためには二重のバックスラッシュを使用する必要があります。トークナイザが FilePermission のターゲット文字列の処理を終え、二重のバックスラッシュを単一のバックスラッシュに変換すると、結果は次の実際のパスになります
"C:\users\Cathy\*"
最後に、プリンシパルベースの grant エントリの例を示します。
grant principal javax.security.auth.x500.X500Principal "cn=Alice" {
  permission java.io.FilePermission "/home/Alice", "read, write";
};
これにより、X500Principal のアクセス権 cn=Alice として実行するコードは /home/Alice を読み取ることも書き込むことも可能になります。

次の例は、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.bar.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 ディレクトリへの読み取りアクセス権と書き込みアクセス権が与えられます。

3.3.2 ポリシーファイル内のプロパティーの展開

ポリシーファイルとセキュリティープロパティーファイルでは、プロパティーの展開が可能です。

プロパティーの展開は、シェルにおける変数の展開に似ています。ポリシーファイルまたはセキュリティープロパティーファイルに次のような文字列がある場合、

"${some.property}"

この文字列は指定されたシステムプロパティーの値まで展開されます。次に例を示します。

permission java.io.FilePermission "${user.home}", "read";
この場合、"${user.home}" は、システムプロパティー user.home の値に展開されます。user.home の値が /home/cathy である場合、上の記述は下の記述と同じになります。
permission java.io.FilePermission "/home/cathy", "read";
プラットフォームにより異なるポリシーファイルを使いやすくするために、${/} という特殊な表記 (${file.separator} の簡略形) も使用できます。これは「${file.separator}」へのショートカットで、次のようにしてアクセス権を定義できます。
permission java.io.FilePermission "${user.home}${/}*", "read";
Solaris システムで、user.home が /home/cathy であれば、これは次のように変換されます。
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 文字は自動的にすべて / に置き換えられます。コードベースが URL であるため、/ に置き換えるのが望ましいといえます。したがって、Windows システムで java.home が C:\j2sdk1.2 に設定されていても、次のように変換されます。
grant codeBase "file:/C:/j2sdk1.2/lib/ext/"
したがって、コードベース文字列では ${/} を使う必要はありません。また、使うべきではありません。

プロパティーの展開は、ポリシーファイル内で、二重引用符で囲まれた文字列が使用できる場所であればどこでも行われます。これには、署名者、コードベース、ターゲット名、動作の各フィールドがあります。

プロパティーの展開が許可されるかどうかは、セキュリティープロパティーファイルの policy.expandProperties プロパティーの値によって決まります。このプロパティーの値が true (デフォルト) の場合は、展開が許可されます。

注: 入れ子のプロパティーは使用できません。次に例を示します。

"${user.${foo}}"
この例では、foo プロパティーが home に設定されている場合であっても、エラーになります。これは、プロパティー構文解析プログラムは入れ子になったプロパティーを認識しないためです。プロパティー構文解析プログラムは、最初の「${」を見つけたら、次に最初の「}」を探し、結果の「${user.$foo}」をプロパティーと解釈しようと試みます。しかし、そのようなプロパティーがない場合はエラーになります。

注: grant エントリ、アクセス権エントリ、または keystore エントリで展開できないプロパティーがある場合、そのエントリは無視されます。たとえば、次のようにシステムプロパティー foo が定義されていない場合、

grant codeBase "${foo}" {
  permission ...;
  permission ...;
};
この grant エントリ内の permission はすべて無視されます。また、次のような場合、
grant {
  permission Foo "${foo}";
  permission Bar;
};
permission Foo... エントリだけが無視されます。また、次のように指定されている場合、
keystore "${foo}";
この場合は、keystore エントリが無視されます。

注: Windows システムでは、文字列中で直接ファイルパスを指定する場合は、単一のバックスラッシュは次のように二重のバックスラッシュで表します。

"C:\\users\\cathy\\foo.bat"
文字列はトークナイザ (java.io.StreamTokenizer) によって処理されますが、そこでは「\」を使用したエスケープ文字列 (改行を表す「\n」など) の使用が許されるので、単一のバックスラッシュを表すためには二重のバックスラッシュを使用する必要があります。トークナイザが文字列の処理を終え、二重のバックスラッシュを単一のバックスラッシュに変換すると、結果は次の実際のパスになります。
"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"

3.3.3 ポリシーファイルにおける一般的な展開

ポリシーファイルでは一般化された形式の展開もサポートされています。たとえば、アクセス権名が次の形式の文字列を含んでいるとします。${{protocol:protocol_data}} このような文字列がアクセス権名に含まれる場合、protocol の値によって実行される展開のタイプが決まり、protocol_data は展開を実行するために使用されます。protocol_data は空にすることもできます。空の場合は、上記の文字列は次のような単純な形式になります。${{protocol}}

デフォルトのポリシーファイルの実装では、次の 2 つのプロトコルがサポートされます。

  1. ${{self}}

    プロトコル self は、${{self}} 文字列全体を 1 つ以上のプリンシパルクラスとプリンシパル名のペアに置き換えることを示します。実際に実行される置き換えは、permission を含む grant 節の内容によって決まります。

    grant 節にプリンシパルの情報が含まれていない場合は、permission は無視されます。プリンシパルベースの grant 節のコンテキストでは、ターゲット名に ${{self}} を含む permission のみが有効です。たとえば、次の grant 節内の BarPermission は常に無視されます。

                grant codebase "www.foo.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.bar.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"
  2. ${{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.bar.example.com/blah/.keystore";
    
                grant codebase "www.foo.example.com" {
                    permission BarPermission "... ${{alias:duke}} ...";
                };
            
    
    上の例の別名 duke に関連付けられている X.509 証明書は、KeyStore (foo.bar.com/blah/.keystore) から取得されます。duke の証明書がサブジェクト識別名として "o=dukeOrg, cn=duke" を指定し、${{alias:duke}} が javax.security.auth.x500.X500Principal "o=dukeOrg, cn=duke" で置き換えられるものとします。

    次のエラー条件に該当する場合、アクセス権エントリは無視されます。

    • keystore エントリが指定されていない
    • alias_name が指定されていない
    • alias_name の証明書を取得できない
    • 取得される証明書が X.509 証明書ではない

3.3.4 アクセス権の割り当て

プリンシパルが特定のコードソースからクラスを実行するとき、セキュリティーメカニズムはポリシーオブジェクトを調べてどのアクセス権を与えるべきかを決定します。この決定は、VM にインストールされた Policy オブジェクトの getPermissions メソッドまたは implies メソッドを呼び出すことにより行われます。

ワイルドカード「*」の使用が認められているなどの理由により、ProtectionDomain 内のコードソースがポリシー内の複数のエントリのコードソースに一致することがあります。

ポリシー内の適切なアクセス権セットを探すために、次のアルゴリズムが使用されます。

1. match the public keys, if code is signed.
2. if a key is not recognized in the policy, ignore the key
   if every key is ignored, treat the code as unsigned.
3. if the keys are matched, or no signer was specified {
       try to match all URLs in the policy for the keys
   }
4. if the keys are matched (or no signer was specified),
   and the URLs are matched (or no codebase was specified) {
       try to match all principals in the policy with
       the principals associated with the current executing thread.
5. if either key, URL, or principals are not matched, use built-in default
       permission, which is the original sandbox permission.
ポリシーエントリの codeBase URL の正確な意味は、最後の文字に依存します。末尾が「/」の codeBase は、指定されたディレクトリ内のすべてのクラスファイル (JAR ファイルを除く) を示します。末尾が「/*」の codeBase は、そのディレクトリ内にあるすべてのファイル (クラスファイルと JAR ファイルの両方) を示します。末尾が「/-」の codeBase は、指定されたディレクトリとその下の全サブディレクトリ内のすべてのファイル (クラスファイルと JAR ファイルの両方) を示します。

たとえば、ポリシー内に「http://www.example.com/-」がある場合は、その Web サイト上のすべてのコードベースはこのポリシーエントリに一致します。一致するコードベースには、「http://www.example.com/j2se/sdk/」および「http://www.example.com/people/gong/appl.jar」があります。

複数のエントリが一致する場合は、それらのエントリ内のすべてのアクセス権が与えられます。つまり、アクセス権は追加割り当てできます。たとえば、鍵 A で署名されたコードにアクセス権 X が与えられ、鍵 B で署名されたコードにはアクセス権 Y が与えられており、特定のコードベースが指定されていない場合、A と B の両方で署名されたコードにはアクセス権 X と Y の両方が与えられます。同様に、コードベースが「http://www.example.com/-」のコードにアクセス権 X が与えられ、「http://www.example.com/people/*」のコードにアクセス権 Y が与えられており、特定の署名者が指定されていない場合は、「http://www.example.com/people/applet.jar」からのアプレットには X と Y の両方のアクセス権が与えられます。

ここでの URL のマッチングは、純粋に構文上のマッチングです。たとえば、あるポリシーに URL「ftp://ftp.sun.com」を指定するエントリがあるとします。このようなエントリは、Java コードを直接 ftp からダウンロードして実行できる場合にだけ有用です。

ローカルファイルシステムの URL を指定する場合、ファイルの URL を使用できます。たとえば Solaris システムの /home/cathy/temp ディレクトリ内のファイルを指定するには、次のようにします。

"file:/home/cathy/temp/*"
Windows システムの C ドライブにある temp ディレクトリ内のファイルを指定するには、次のようにします。
"file:/c:/temp/*"
注:コードベースの URL には、プラットフォームにかかわらず、必ず「/」(「\」記号ではなく) を使用してください。

次のような、絶対パスを使用することもできます。

"/home/gong/bin/MyWonderfulJava"

3.3.5 デフォルトのシステムポリシーファイルとユーザーポリシーファイル

Policy のリファレンス実装では、1 つまたは複数のポリシー構成ファイルからポリシーを指定できます。構成ファイルは、特定のコードソースからのコードに許可されるアクセス権を指定します。

ポリシーファイルは、単純なテキストエディタ、または後述する PolicyTool ユーティリティーを使って作成できます。

デフォルトでは、システム全体のポリシーファイルが 1 つあり、ユーザーポリシーファイルが 1 つあります。

システムポリシーファイルは、デフォルトでは次の場所にあります。

{java.home}/lib/security/java.policy  (Solaris)
{java.home}\lib\security\java.policy  (Windows)
ここで java.home は Java 2 SDK がインストールされているディレクトリを示すシステムプロパティーです。

ユーザーポリシーファイルは、デフォルトでは次の場所にあります。

{user.home}/.java.policy  (Solaris)
{user.home}\.java.policy  (Windows)
ここで user.home は、ユーザーのホームディレクトリを示すシステムプロパティーです。

Policy が初期化されると、まずシステムポリシーがロードされ、次に、ロードされたシステムポリシーにユーザーポリシーが追加されます。どちらのポリシーも存在しない場合は、組み込みポリシーが使われます。組み込みポリシーは、オリジナルのサンドボックス (sandbox) ポリシーと同じものです。

ポリシーファイルの場所は、セキュリティープロパティーファイルの中で指定されています。セキュリティープロパティーファイルは、次の場所にあります。

{java.home}/lib/security/java.security  (Solaris)
{java.home}\lib/security\java.security  (Windows)
ポリシーファイルの場所は、次のような形式の名前を持つプロパティーの値として指定されています。
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
「http://」の形式のものも含めて、実際には複数の URL を指定でき、指定したポリシーファイルのすべてがロードされます。また、上に示したポリシーファイルの指定のうち、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=pURL SomeApp
ここで pURL は、ポリシーファイルの位置を示す URL です。指定されたポリシーファイルは、セキュリティープロパティーファイルで指定されたすべてのポリシーファイルに追加されてロードされます。引数「-Djava.security.manager」により、デフォルトのセキュリティーマネージャーが確実にインストールされるので、「アプレットおよびアプリケーションのセキュリティー管理」の説明にあるように、アプリケーションはポリシーチェックを受けます。アプリケーション SomeApp がセキュリティーマネージャーをインストールする場合は、-Djava.security.manager 引数を指定する必要はありません。

次のように、「==」の付いた形式を使うと、ここで指定されたポリシーファイルだけがロードされ、ほかのポリシーファイルは無視されます。

java -Djava.security.manager -Djava.security.policy==pURL SomeApp
アプレットビューアにポリシーファイルを渡す場合も、次のように「-Djava.security.policy」引数を使います。
appletviewer -J-Djava.security.policy=pURL  myApplet
注: セキュリティープロパティーファイルで policy.allowSystemProperty プロパティーに false が設定されている場合は、-Djava.security.policy のポリシーファイルの値は (java コマンドと appletviewer コマンドのどちらの場合も) 無視されます。デフォルトは true です。

3.3.6 Policy の評価のカスタマイズ

Policy クラスの現在の設計は、すべての場合に適用できる包括的なものではありません。その点については考察が重ねられ、多くの場合に適したメソッドの呼び出しが確実にできるよう部分的な改良が進められています。それまでの間、デフォルトのポリシークラスを別のポリシークラスに置き替えることができます。ただし、置き換えるポリシークラスが抽象 Policy クラスのサブクラスであり、getPermissions メソッド (および必要に応じてほかのメソッド) を実装していることが条件です。

Policy のリファレンス実装は、「policy.provider」セキュリティープロパティー (セキュリティープロパティーファイル内) の値を、目的の Poliocy 実装クラスの完全修飾形の名前に設定し直すことにより変更できます。セキュリティープロパティーファイルは、次の名前のファイルです。

{java.home}/lib/security/java.security (Solaris)
{java.home}\lib\security\java.security (Windows)
{java.home} は、実行環境がインストールされたディレクトリ (Java 2 SDK 内の jre ディレクトリ、または Java 2 Runtime Environment の最上位ディレクトリ) を参照します。

policy.provider プロパティーは、ポリシークラスの名前を指します。デフォルトは次のとおりです。

policy.provider=sun.security.provider.PolicyFile
カスタマイズするには、次のように、このプロパティー値に別のクラスを指定します。
policy.provider=com.mycom.MyPolicy
MyPolicy クラスは、java.security.Policy のサブクラスでなければなりません。このような、ポリシークラスのオーバーライドはあくまでも一時的な解決策であり、より包括的なポリシー API が設計されれば不要になります。

3.4 java.security.GeneralSecurityException

これは、新しい例外クラスで、java.lang.Exception のサブクラスです。これは、セキュリティーおよびセキュリティーパッケージ関連の例外を 2 種類にすることを意図して追加されました。 このような例外は、ある種のセキュリティー違反が検出された場合にだけスローされます。たとえば、あるコードがアクセス権のないファイルにアクセスしようとする場合に、この種の例外がスローされます。アプリケーション開発者は、任意でそれらの例外をキャッチできます。 これらの例外はセキュリティーに関連したものですが、必要不可欠というわけではありません。たとえば、無効な鍵を渡すことはセキュリティー違反ではないと考えられますが、その鍵は開発者によりキャッチおよび処理される必要があります。

RuntimeException のサブクラスである java.security パッケージ内に、現時点で 2 つの例外があります。下位互換性により、現時点ではこれらの例外は変更できません。将来この問題を再検討します。



目次 | 前へ | 次へ
Copyright © 1997-2002 Sun Microsystems, Inc. All Rights Reserved.
目次 | 前へ | 次へ

Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.