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>>」は特別な文字列で、システム内のすべてのファイルを表します。Solaris、LinuxまたはMac OS Xシステムでは、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"
全プラットフォーム共通のファイル記述言語ができるまでは、文字列はプラットフォームごとに異なる形式で指定する必要があります。また、「*」や「-」のようなメタ・シンボルを使用して特定のファイル名を表すことはできません。これは、さしあたり許容できる程度の小さな制限事項だと考えます。最後に、Solaris、LinuxおよびMac OS Xシステムでは「/-」と「<<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(これは基本的にDNSルックアップ)です。アクション「resolve」は、「accept」、「connect」および「listen」によって暗黙的に定義されます。つまり、ホストからの入力接続を待機または受け付けるか、ホストへの出力接続を開始できるユーザーは、リモート・ホストの名前をルックアップできるはずです。

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

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があります。

特定のアクセス権の割当てのリスクを列挙した表およびアクセス権を必要とするすべてのJava 2 SDKの組込みメソッドの表など、アクセス権の詳細は、「Java Development Kitでのアクセス権」を参照してください。


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://example.com/のコードに付与するポリシー・ファイル・エントリの例を示します。

grant codeBase  "http://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の下で実行中のアプリケーション)がセキュリティの対象であるアクションを実行するためには、そのアプレット(またはアプリケーション)にはその特定のアクションのためのアクセス権を与えられていることが必要です。唯一の例外として、コードは必ず、同じCodeSource、およびそのCodeSourceのサブディレクトリからのファイルの読取りアクセス権を自動的に持ちます。この場合は、明示的なアクセス権は必要ありません。

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エントリは無視されるため、ファイルのgrantエントリの外であれば、どこに指定してもかまいません。構文は次のとおりです。

keystore "some_keystore_url", "keystore_type";
ここで、「some_keystore_url」にはキーストアのURL位置を指定し、「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エントリは、指定したコード・ソースとプリンシパルに一連のアクセス権を与えます。

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://example.comからロードされたコードに、2つのアクセス権を与えます。
grant codeBase "http://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システムでは、文字列中で直接ファイル・パスを指定する場合は、パス内の実際の単一のバックスラッシュごとに、次のように2つのバックスラッシュを含める必要があります。

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の値に展開されます。そのプロパティの値が/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がセキュリティ・マネージャをインストールする場合は、これは必要はありません。

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

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」セキュリティ・プロパティ(セキュリティ・プロパティ・ファイル内)の値を、目的のPolicy実装クラスの完全修飾形の名前に設定し直すことにより変更できます。セキュリティ・プロパティ・ファイルは、次の名前のファイルです。

{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 © 1993, 2016, Oracle and/or its affiliates. All rights reserved.