目次 | 前の項目 | 次の項目 Java セキュリティーアーキテクチャー


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


3.1 Permission クラス

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

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

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

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

abstract クラス java.security.Permission には、java.security.PermissionCollection という名前の abstract クラスと 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 (directory/ と同じ)
directory/file
directory/* (このディレクトリ内のすべてのファイル)
* (現在のディレクトリ内のすべてのファイル)
directory/- (このディレクトリ下のファイルシステム内のすべてのファイル)
- (現在のディレクトリ下のファイルシステム内のすべてのファイル)
"<<ALL FILES>>" (ファイルシステム内のすべてのファイル)
"<<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") を表します。

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

FilePermission p = new FilePermission("c:\\temp\\foo", "read");
文字列はトークナイザ (java.io.StreamTokenizer) によって処理されますが、そこでは「\」を使ったエスケープ文字列 (改行を表す「\n」など) が許されるので、単一の「\」記号を表すためには 2 つの連続した「\」記号を使う必要があります。トークナイザが FilePermission のターゲット文字列の処理を終え、2 つの連続した「\」記号を単一の「\」記号に変換すると、結果は次の実際のパスになります

"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 (単一ホスト)
IP address (単一ホスト)
localhost (ローカルマシン)
"" ("localhost" と同等)
hostname.domain (ドメイン内の単一ホスト)
hostname.subdomain.domain
*.domain (ドメイン内のすべてのホスト)
*.subdomain.domain
* (すべてのホスト)
つまり、ホストは、DNS 名、数値の IP アドレス、「localhost」 (ローカルマシンの場合)、"" (「localhost」を指定するのと同じ) のどれかで表現されます。

DNS 名によるホスト指定には、ワイルドカード「*」を 1 回使用できます。これを使う場合は、「*.sun.com」のように一番左の位置に使います。

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

N (a single port)
N- (N 以上のすべてのポート)
-N (N 以下のすべてのポート)
N1-N2 (N1 と N2 を含むこの間のすべてのポート)
上の形式で、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.sun.com","accept");
p = new SocketPermission("204.160.241.99","accept");
p = new SocketPermission("*.com","connect");
p = new SocketPermission("*.sun.com:80","accept");
p = new SocketPermission("*.sun.com:-1023","accept");
p = new SocketPermission("*.sun.com:1024-","connect");
p = new SocketPermission("java.sun.com:8000-9000",
         "connect,accept");
p = new SocketPermission("localhost:1024-",
          "accept,connect,listen");
SocketPermission("java.sun.com:80,8080","accept") と SocketPermission("java.sun.com,javasun.sun.com","accept") は、有効なソケットアクセス権ではありません。

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


3.1.7 java.security.BasicPermission

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

BasicPermission の名前は、指定されたアクセス権の名前です (たとえば 「exitVM」、「setFactory」、「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.10.17 アクセス権の意味

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

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

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

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

アクセス権の詳細については、http://java.sun.com/j2se/sdk/1.2/docs/guide/security/permissions.html を参照してください。アクセス権を必要とする Java 2 SDK 組み込みのメソッド、および特定のアクセス権の割り当てに伴う危険性について、一覧で説明されています。


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

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

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

最初に、abstract クラス 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://java.sun.com/ のコードに付与するポリシーファイルの例を示します。

grant codeBase  "http://java.sun.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 エントリを置きます (次を参照)。

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

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

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

policy.url.1=http://foo.bar.com/blah/some.policy
ポリシーファイルに次のようなエントリがある場合は、

keystore ".keystore";
キーストアは次の位置からロードされます。

http://foo.bar.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 など) はできません。

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

コードベース URL の正確な意味は、最後の文字に依存します。末尾が「/」のコードベースは、指定されたディレクトリ内のすべてのクラスファイル (JAR ファイルでない) に一致します。末尾が「/*」のコードベースは、そのディレクトリ内にあるすべてのファイル (クラスファイルと JAR ファイルの両方) に一致します。末尾に「/-」の付いたコードベースは、ディレクトリのすべてのファイル (クラスファイルと JAR ファイルの両方)、および再帰的にそのディレクトリのサブディレクトリにあるすべてのファイルを表します。

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

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

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

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

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

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

キーストアの別名の置き換え

principal 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://java.sun.com からロードされたコードに、2 つのアクセス権を与えます。

grant codeBase "http://java.sun.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 システムでは、文字列中で直接ファイルパスを指定する場合は、「\」記号は次のように 2 つの「\」記号で表します。

grant signedBy "Roland" {
  permission java.io.FilePermission "C:\\users\\Cathy\\*", "read";
};
文字列はトークナイザ (java.io.StreamTokenizer) によって処理されますが、そこでは「\」を使用したエスケープ文字列 (改行を表す「\n」など) の使用が許されるので、単一の「\」記号を表すためには 2 つの連続した「\」記号を使用する必要があります。トークナイザが FilePermission のターゲット文字列の処理を終え、2 つの連続した「\」記号を単一の「\」記号に変換すると、結果は次の実際のパスになります

"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.com",
        signedBy "Duke",
        principal javax.security.auth.x500.X500Principal "cn=Alice" {
    permission java.io.FilePermission "/tmp/games", "read, write";
  };
これにより、「Duke」によって署名され、「www.games.com」からダウンロードされたコードが「cn=Alice」によって実行されると、「/tmp/games」ディレクトリへの読み取り権と書き出し権が与えられます。

次の例は、キーストアの別名を置き換える grant 文を示しています。

  keystore "http://foo.bar.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}」へのショートカットで、次のようにしてアクセス権を定義できます。

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}」) をプロパティーと解釈しようと試みます。しかし、そのようなプロパティーがない場合はエラーになります。

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

grant codeBase "${foo}" {
  permission ...;
  permission ...;
};
この付与エントリ内のアクセス権はすべて無視されます。また、次のような場合、

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

keystore "${foo}";
キーストアエントリは無視されます。

注 -Windows システムでは、文字列中で直接ファイルパスを指定する場合は、「\」記号は次のように 2 つの「\」記号で表します。

"C:\\users\\cathy\\foo.bat"
文字列はトークナイザ (java.io.StreamTokenizer) によって処理されますが、そこでは「\」を使用したエスケープ文字列 (改行を表す「\n」など) の使用が許されるので、単一の「\」記号を表すためには 2 つの連続した「\」記号を使用する必要があります。トークナイザが文字列の処理を終え、2 つの連続した「\」記号を単一の「\」記号に変換すると、結果は次の実際のパスになります。

"C:\users\cathy\foo.bat"
文字列中のプロパティーの展開は、トークナイザがその文字列の処理を完了したあとに行われます。たとえば、次のような文字列があるとします。

"${user.home}\\foo.bat"
上のような文字列の場合、まずトークナイザが文字列を処理して、2 つの「\」記号を 1 つの「\」記号に置き換えると次のようになります。

"${user.home}\foo.bat"
次に、user.home の値が C:\users\cathy であれば、${user.home} プロパティーが展開されて次のようになります。

"C:\users\cathy\foo.bat"
もちろん、プラットフォームに依存しないために、明示的にスラッシュを使うのではなく、${/} プロパティーを使って次のように指定する方が望ましいと言えます。

"${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.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.com/blah/.keystore";
    
                grant principal "duke" {
                    permission BarPermission "... ${{self}} ...";
                };
    	
    上の例では、初めに "duke" が次のように展開されます。
    javax.security.auth.x500.X500Principal "cn=Duke"
    キーストアの別名に関連付けられた X.509 証明書 duke が「cn=Duke」というサブジェクト識別名を持っているものとします。次に、${{self}} が、grant 句内で展開されたその同じプリンシパル情報に置き換えられます。
    javax.security.auth.x500.X500Principal "cn=Duke".
  2. ${{alias:alias_name}}

    プロトコル alias は、java.security.KeyStore 別名の置換を示します。KeyStore entry に指定された KeyStore が使用されます。alias_nameKeyStore の別名を表します。${{alias:alias_name}} は javax.security.auth.x500.X500Principal "DN" で置き換えられます。ここで、DNalias_name に属する証明書のサブジェクト識別名です。例を示します。

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

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

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

3.3.4 アクセス権の割り当て

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

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

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

1. コードが署名付きの場合は、公開鍵をマッチングする
2. ある鍵がポリシー内で認識されない場合は、その鍵を無視する
   すべての鍵が無視された場合は、そのコードを署名なしとして扱う
3. 鍵がマッチした場合、または署名者が指定されていない場合は、{
       それらの鍵のポリシー内のすべての URL のマッチングを試みる
   }
4. 鍵がマッチした場合 (または署名者が指定されていない場合),
   または URL がマッチした場合 (またはコードベースが指定されていない場合) は、{
       ポリシー内のすべてのプリンシパルと
       現在実行中のスレッドに関連付けられているプリンシパルとのマッチをすべて試みる
5. 鍵、URL、またはプリンシパルのどれかがマッチしない場合は、組み込みのデフォルトアクセス権
       (オリジナルの sandbox アクセス権) を使用する
ポリシーエントリのコードベース URL の正確な意味は、最後の文字に依存します。末尾が「/」のコードベースは、指定されたディレクトリ内のすべてのクラスファイル (JAR ファイルでない) に一致します。末尾が「/*」のコードベースは、そのディレクトリ内にあるすべてのファイル (クラスファイルと JAR ファイルの両方) に一致します。末尾に「/-」の付いたコードベースは、ディレクトリのすべてのファイル (クラスファイルと JAR ファイルの両方)、および再帰的にそのディレクトリのサブディレクトリにあるすべてのファイルを表します。

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

複数のエントリがマッチする場合は、それらのエントリ内のすべてのアクセス権が与えられます。つまり、アクセス権は追加割り当てできます。たとえば、鍵 A で署名されたコードにアクセス権 X が与えられ、鍵 B で署名されたコードにはアクセス権 Y が与えられており、特定のコードベースが指定されていない場合、A と B の両方で署名されたコードにはアクセス権 X と Y の両方が与えられます。同様に、コードベースが「http://java.sun.com/-」のコードにアクセス権 X が与えられ、「http://java.sun.com/people/*」のコードにアクセス権 Y が与えられており、特定の署名者が指定されていない場合は、「http://java.sun.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/*"
Note:コードベースの 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 から処理を開始して、番号が連続して増加している間、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 コマンドのどちらの場合も) 無視されます。policy.allowSystemProperty プロパティーのデフォルト値は true です。


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

Policy クラスの現在の設計は、すべての場合に適用できる包括的なものではありません。その点については考察が重ねられ、多くの場合に適したメソッドの呼び出しが確実にできるよう部分的な改良が進められています。それまでの間、デフォルトのポリシークラスを別のポリシークラスに置き替えることができます。ただし、置き換えるポリシークラスが abstract 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=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.