Javaは言語仕様レベルのセキュリティモデルとして、主として次の三つの階層で考えます:
開発者の主たる関心は、クラスがロードされてからの権限チェックにあるでしょう。
クラスローダはクラスの依存関係を解決して必要なものをロードするもので、次の三つのものがあります。クラスローダ間には親子関係があり、デフォルトでは親から子へ向かって順番に探索されます(委譲モデル)。
rt.jar, i18n.jar をロードするjre/lib/ext 内のインストール型オプション・パッケージをロードするクラスローダは、抽象クラス java.lang.ClassLoader のサブクラスです。色々な拡張が存在し、例えば、スレッドのコンテキストクラスローダー、アクセスコントローラで使う java.security.SecureClassLoader、そのサブクラスの java.net.URLClassLoader などが挙げられ、アプレットやサーブレットのクラスローダーは、各製品ごとに独自に実装されています。
自分でクラスローダーを実装する場合は、抽象クラス ClassLoader を継承して、メソッド findClass() と loadClassData() をオーバーライドします。暗号化したクラスをロードしたり、親のクラスローダに処理を委譲しないようなカスタム・クラスローダーを実装することが考えられます。
デフォルトでは、アプリケーションのクラスがロードされるとき、
loadClass() が呼ばれ、findClass() を呼んで "*.class" をロードし、defineClass() で "*.class" のバイト配列(バイトコード)からクラスを構築します。悪意のあるコードからシステムを保護するために、JVMがコードの実行範囲を狭めた領域のことをサンドボックス(砂場)と呼びます。Javaプログラムがリソースに対して許可されている範囲のことです。一般に、ネットワーク越しにロードされたクラスのサンドボックスは厳重に制限されています。
Javaサンドボックスに対する制御の責任を負うのがセキュリティマネージャ (java.lang.SecurityManager)
です。デフォルトでは、ローカルのアプリケーションにはセキュリティマネージャがインストールされず、すべての処理が可能です。一方、アプレットには、厳
格なセキュリティマネージャがインストールされ、ローカルのファイルシステムにアクセスしたり、破損させたり、アプレットのロード元以外のホストに接続す
ることを防止しています。
サーブレットの場合でも、適切なポリシを実装するセキュリティマネージャを実装することで、予期せず混入したミスや悪意のあるコードから、サーバを保護することが可能です。
セキュリティマネージャをインストールするには、コードに次の行を埋め込みます:
System.setSecurityManager(new SecurityManager());
java実行時引数にシステムプロパティ"java.security.manager"を指定することでも同様の効果が得られます:
>java -Djava.security.manager MyAppl
SDK 1.2以降のJava2で、セキュリティマネージャに代わって登場したのがアクセスコントローラー(java.security.AccessController)です。基本的な動作としては、セキュアクラスローダーが定義したパラメーターをセキュリティマネージャが受け取り、セキュリティマネージャはセキュリティーポリシに照らしてアクセス権チェックをする処理をアクセスコントローラーに委譲します。
直接アクセスコントローラに問い合わせることもできます。例えば、"/tmp"内のすべてのファイルに対する読み書き権限をチェックするためにリスト1のコードが使えます。
リスト1. アクセス権をチェックするコード
try {
// 問い合わせるアクセス権を意味するオブジェクトを生成
FilePermission perm = new FilePermission("/tmp/*", "read, write");
// アクセスコントローラにてチェック
AccessController.checkPermission(perm);
...
// 省略
...
} catch (AccessControlException ex) {
// アクセス権チェックが失敗すると例外が発生
ex.printStackTrace();
}
アプリケーションに許す、java.io.FilePermissionのようなアクセス権は、ポリシファイルと呼ばれるテキストファイルで設定することができます。次に、ポリシーファイルとアクセス権の種類について説明します。