セキュリティマネージャおよび J2SE Development Kit

最終更新日: 2001 年 5 月 1 日



はじめに
セキュリティモデルの進化
セキュリティマネージャの進化
セキュリティマネージャのメソッド
JDK 1.1 のセキュリティマネージャ
J2SE Development Kit でのセキュリティマネージャ
java.lang.SecurityManager をデフォルトのセキュリティマネージャとしてインストールする
クラスローダおよびクラスローダ深度用メソッドの変更
1.1 スタイルのセキュリティマネージャのポーティング方法
SecurityManager メソッドの変更とオーバーライドに関するアドバイス


はじめに

このドキュメントでは、JDK のセキュリティマネージャに加えられた変更について説明します。この変更により、アプリケーションのデフォルトのセキュリティマネージャとしてこのセキュリティマネージャを使用できるようになりました。

セキュリティモデルの進化

JDK 1.1 では、ローカルアプリケーションおよび適切にデジタル署名されたアプレットは通常は信頼され、ファイルシステムなどの重要なシステムリソースへの完全なアクセス権を持っていましたが、署名されていないアプレットは信頼されず、限られたりソースにしかアクセスできませんでした。どのリソースへのアクセスを許可するか決める責任は、セキュリティマネージャが負っていました。

J2SE Development Kit のセキュリティアーキテクチャはポリシーベースで、きめ細かなアクセス管理が可能です。ロードされたコードには、現在有効なセキュリティポリシーをもとに「アクセス権」が割り当てられます。個々のアクセス権には、特定のリソースに対して許可されるアクセスが指定されます。たとえば、特定のファイルやディレクトリに対する「読み取り」と「書き込み」のアクセスや、特定のホストとポートへの「接続」アクセスなどです。ポリシーは、署名者や場所の異なるコードに与える権限を指定します。ポリシーは、設定可能な外部のポリシーファイルを使って初期化できます。コードに対し明示的にアクセス権が与えられていなければ、そのコードから、そのアクセス権で保護されたリソースにはアクセスできません。アクセス権とポリシーのこの新しい概念により、JDK ではきめ細かで調節しやすく、柔軟で拡張性の高いアクセス管理を提供できます。アプレットだけでなく、アプリケーション、Beans、サーブレットを含むすべての Java コードに、このようなアクセス管理を指定できるようになりました。

Java のセキュリティアーキテクチャの詳細については、セキュリティドキュメントを参照してください。

セキュリティマネージャの進化

セキュリティマネージャのメソッド

SecurityManager クラスには、名前が check で始まるメソッドが多数あります。たとえば checkReadcheckConnect などです。Java ライブラリのさまざまなメソッドが、セキュリティが重視される操作を実行する前に毎回 check メソッドを呼び出します。これにより、セキュリティマネージャには、例外をスローして操作の実行を阻止する機会が与えられます。セキュリティマネージャのルーチンは、その操作が許可されているときには単に呼び出し元に戻るだけですが、その操作が許可されていないときには SecurityException をスローします。この規則の唯一の例外は checkTopLevelWindow で、これはブール値を返します。

SecurityManager クラスに含まれる、もうひとつの主要なタイプのメソッドは、クラスローダの存在と深度に関係するクラスです。

JDK 1.1 のセキュリティマネージャ

JDK 1.1 では、java.lang.SecurityManager クラスは abstract クラスでした。セキュリティマネージャの check メソッドは、デフォルト実装では例外をスローしました。クラスローダと深度に関連するクラスは適切に、多くの場合はネイティブコードで実装されました。

セキュリティマネージャをインストールしようとするアプリケーション (ブラウザなど) はすべて、独自のセキュリティマネージャを作成して、デフォルトで例外をスローするメソッドの固定実装を適切に提供する必要がありました。これらのメソッドは、主に check メソッドでした。

JDK 1.1 アプレットのセキュリティマネージャモデルを基にしたセキュリティマネージャは、一般的には次の 2 点に基づいてアクセス管理を決定します。

  1. クラスローダを持つクラス (JDK 1.1 のアプレット) がスタック上にあるかどうか

  2. クラスローダの深度 (クラスローダを使って定義されたクラスメソッドが、スタックのどれくらいの深さで最近発生したか)

これらのタイプの決定は、クラスローダの存在と深度に関係する SecurityManager メソッドの呼び出しによって行われていました。たとえば、典型的な 1.1 スタイルのセキュリティマネージャには、次のような checkExit メソッドがあります。

public void checkExit(int status) {
if (inClassLoader()) {
throw new SecurityException(..);
       } 
     }

このような checkExit メソッドは、クラスローダを使って定義されたクラス (アプレット) がスタックにあるときは Runtime.exit の呼び出しを許可しませんでした。これは前者のケースの例で、クラスローダを持つクラスがスタックにあるかどうかをチェックします。後者のケース (クラスローダの深度) の例は、次のようなものです。

public void checkCreateClassLoader() {
if (classLoaderDepth() == 2) {
throw new SecurityException();
         }
      }

このメソッドは、クラスローダの深度が 2 であってはならないことを示しています。つまり、checkCreateClassLoader を呼び出したメソッドを呼び出すメソッドは、クラスローダで定義されたクラスにあってはなりません。たとえば、java.lang.ClassLoader のコンストラクタは checkCreateClassLoader を呼び出します。これは、java.lang.ClassLoader のコンストラクタを呼び出すメソッドが、クラスローダを持っていてはならないことを意味します。したがって、アプレットはクラスローダを直接作成できないことになります。

2 つのメソッドはどちらもアプレットの実行を阻止しようとしますが、2 つには大きな違いがあります。前者のケースでは、スタックのどこかにアプレットがあると checkExit が例外をスローします。これは、組み込みの JDK コードであっても、アプレットから呼び出された場合には、VM を終了できないことを意味します。後者のケースでは、JDK コードはアプレットから呼び出された場合にも、クラスローダを作成することができます。その理由は、使用されるのはクラスローダを持つクラスの深度であり、それが存在するという事実ではないからです。

J2SE Development Kit でのセキュリティマネージャ

JDK では、java.lang.SecurityManager クラスをアプリケーションのデフォルトのセキュリティマネージャとして使用できるよう、多くの変更が加えられました。特に次の点が重要です。

java.lang.SecurityManager をデフォルトのセキュリティマネージャとしてインストールする

java.lang.SecurityManager は abstract クラスでなくなったので、デフォルトのセキュリティマネージャとしてインストールして使用できるようになりました。これを行うには、VM を起動するときにシステムプロパティを設定します。

java -Djava.security.manager YourApp
別の方法として、次のコードを使ってアプリケーションから直接インストールすることもできます。
System.setSecurityManager(new SecurityManager());
デフォルトのセキュリティマネージャの動作は、ポリシーファイルを変更することによってカスタマイズできます。詳細については、ポリシーファイルのセキュリティガイドを参照してください。

クラスローダおよびクラスローダ深度用メソッドの変更

JDK では、クラスローダとクラスローダ深度に関連する SecurityManager メソッドは推奨されておらず、どの check メソッドからも呼び出されません。新しいセキュリティマネージャではこれらのメソッドは使用せず、既存のセキュリティマネージャからも削除することをお勧めします。ただし、これらのメソッドは旧バージョンとの互換性のために残されており、JDK でも 1.1 スタイルのセキュリティマネージャが動作するように変更されました。

これらのメソッドを次に挙げます。

  • currentClassLoader
  • currentLoadedClass
  • inClassLoader
  • classLoaderDepth

クラスローダと深度に関連するメソッドの修正

クラスローダと深度に関連するメソッドはすべて、次の 3 つの点で修正されました。

  1. これらのメソッドはシステムクラスローダを無視します。システムクラスローダとは、システムクラスローダ (ClassLoader.getSystemClassLoader によって返される) またはその祖先のひとつに等しいクラスローダであると定義されます。

    システムクラスローダによってロードされたクラスには、アプリケーションクラス (CLASSPATH からロードされる)、拡張クラス、組み込み JDK クラスがあるので、これらのメソッドはこの修正により、これらのコードを無視することができます。

    カスタムセキュリティマネージャをインストールしているアプリケーションを実行する場合で、かつそのセキュリティマネージャが JDK の CLASSPATH からロードされる場合には、そのセキュリティマネージャには、システムクラスローダが関連付けられます。JDK 1.1 ではアプリケーションクラスはクラスローダを持ちません。ユーザがカスタムセキュリティマネージャ内から classLoaderDepth のようなメソッドを呼び出す予定で、またそのメソッドがシステムクラスローダによりロードされたクラスを無視するように変更されていない場合には、そのメソッドは常に 0 を返します。これは便利とはいえません。同様に、クラスローダメソッドがシステムクラスを無視するように変更されておらず、カスタムのセキュリティマネージャが CLASSPATH からロードされる場合にも、たとえば「classLoaderDepth() == 2」のときに操作を許可しないという方法で、セキュリティマネージャが決定を行うような場合には、セキュリティホールが生じます(実際は「classLoaderDepth() <= 2」であるべき)。

  2. これらのメソッドは、スタック上で「特権付き」のマークがつけられているメソッドに到達すると、チェックを終了します(java.security.AccessController.doPrivileged() および「特権ブロックのための API」を参照)。

  3. これらのメソッドは、AllPermission が与えられているセキュリティコンテキストを、スタック上にクラスローダが存在しないかのように取り扱います。

1 番目と 2 番目の変更の例として、JDK でセキュリティマネージャのインストール後にファイルを開くなどの操作を行う場所があります。1.1 スタイルのセキュリティマネージャには、次のような checkRead メソッドを持つものがあります。

public void checkRead(String file) {
if (inClassLoader()) {
throw new SecurityException(..);
         } 
       }

JDK のコードを修正しないと、JDK 自体がファイルを読み込もうとしたときに、システムクラスローダでないクラスローダがスタック上に存在する場合には、JDK で実行するようなチェックがセキュリティ例外を引き起こします。新しいセキュリティモデルでは、呼び出し元に対して許可されていない可能性のある操作を実行しようとする JDK コードはすべて、doPrivileged ブロックを持ちます。inClassLoader は単に、「特権付き」コードを含むフレームまでのスタックを調べるだけであり、スタックの一番上のコードはシステムクラスローダまたはその上位クラスによりロードされる JDK コードなので、inClassLoader メソッドは false を返し、読み取りを許可します。

クラスローダ深度の維持

先に説明したように、1.1 アプレットのセキュリティマネージャを基にしたセキュリティマネージャは、アクセス管理の決定の一部をクラスローダ深度に基づいて行います。例として、前述した checkCreateClassLoader メソッドをもう一度示します。

public void checkCreateClassLoader() {
if (classLoaderDepth() == 2) {
throw new SecurityException();
          }
       }
JDK では、1.1 スタイルのセキュリティマネージャで使用されていたとおりに、スタック深度を維持しようとしました。たとえば、java.security.SecureClassLoader のコンストラクタは、そのスーパークラス (ClassLoader) のコンストラクタが同じことを行うとしても、SecurityManager.checkCreateClassLoader への明示的な呼び出しを行います。SecureClassLoader のコンストラクタにチェック機能がない場合は、クラスローダの深度は常に 2 よりも大きいため、1.1 スタイルのセキュリティマネージャは信頼されないクラスに対して SecureClassLoader を拡張してクラスローダを構築することを許可します。

1.1 スタイルのセキュリティマネージャのポーティング方法

セキュリティマネージャを JDK 環境で実行する前に、まず自分のカスタムセキュリティマネージャのメソッドをすべて解析しておくことを強くお勧めします。解析を行わないと、セキュリティホールが生じたり、JDK が適切に動作しなくなることがあります。これは、1.1 スタイルのセキュリティマネージャが弱い性質を持っているためです。

可能なら、1.2 の SecurityManager のデフォルト実装を使うようにします。これは、ユーザと管理者に対して一貫性のある動作を提供するのに役立ちます。これが不可能なら、少なくとも checkXXX メソッドの中でセキュリティ例外をスローする前に super.checkXXX を呼び出すようにしてください。これにより、アクセス管理アルゴリズムの使用が可能になり、JDK 自体が正しく機能するようになります。

JDK では、SecurityManager check メソッドの呼び出しに使用されていた既存のコードは、変更されていません。セキュリティチェックの必要な新しいコードについては、呼び出しが SecurityManager.checkPermission に対して行われ、新しい SecurityManager check メソッドは追加されません。たとえば、新しく追加された java.lang.System.setProperty メソッドは、java.util.PropertyPermission アクセス権で checkPermission を呼び出します。

SecurityManager クラスを拡張して既存のメソッドをオーバーライドする場合は、注意が必要です。たとえば、checkRead(String file) メソッドをオーバーライドして常にセキュリティ例外をスローするようにすると、JDK 自体が正しく動作しなくなることがあります。つまり、一部の JDK コードでファイルを開く必要がある場合に (プロパティファイルの読み込みや、JAR ファイルのロードなどのため)、読み取りのたびにセキュリティ例外をスローすると、ファイルを開く操作が必ず失敗することになります。

一般に、デフォルトのメソッドをオーバーライドするのは、セキュリティの緩和の目的でのみ行うべきであり、セキュリティの強化の目的には行うべきではありません。セキュリティを強化したい場合には、デフォルトのポリシーファイルの修正、またはカスタムの java.security.Policy オブジェクトのインストールのどちらかまたは両方を行います。詳細については、ポリシーファイルのセキュリティガイドを参照してください。

一般に、セキュリティマネージャのメソッドをオーバーライドするときは、オーバーライドされた super.checkXXX メソッドが例外をスローする位置に、checkXXX メソッドへの呼び出しを記述する必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkRead(String file) {
if (someCustomSecurityCheckFails()) {
super.checkRead(file);
          }
        }
      }
    
カスタムのセキュリティチェックが失敗した場合には、次に super.checkRead が呼び出されます。checkRead のデフォルト実装では checkPermission が呼び出され、これはデフォルトで AccessController に問い合わせを行います。AccessController を呼び出すことにより、ファイルを読み出す前に AccessController.doPrivileged を行なったシステムコードは、そのファイルの読み取りに成功します。それ以外のすべてのコードはその時点で有効なポリシーに従い、そのファイルへのアクセス権が与えられていない場合には、アクセス管理例外がスローされます。

checkXXX メソッドには、それをオーバーライドするときに super.checkXXX メソッドを呼び出してはならないものがあります。その理由は、これらのメソッドのデフォルト実装は、オーバーライド後のメソッドで実装しているポリシーほど厳しくない場合があるからです。たとえば、デフォルトの checkAccess(ThreadGroup g) メソッドは、システムスレッドグループだけを保護します。独立したスレッドグループ (アプレットスレッドグループなど) をお互いから保護しようとする場合は、通常はセキュリティ例外をスローする位置で super.checkAccess を呼び出すと、カスタムチェックの目的が損なわれるため、通常その位置ではスローしません。その代わり、オーバーライドしたメソッドの最初のステートメントで、super.checkAccess への呼び出しを記述することができます。

次に例を示します。

public class AppletSecurityManager extends SecurityManager {

public void checkAccess(ThreadGroup g) {
// a call to super will throw an exception if someone
// is trying to modify the system thread group
super.checkAccess(g);
          ...
// now perform checks based on which applet thread group
// the current caller is in to see if they can modify thread group g.
          ...
      }
    

次に、各メソッドをオーバーライドする方法を説明します。

SecurityManager メソッドの変更とオーバーライドに関するアドバイス

ここでは、JDK で java.lang.SecurityManager メソッドに加えられた変更のリストを示し、オーバーライドを実行する際のアドバイスを行います。これらのメソッドの詳細については、SecurityManager クラスの Java ドキュメントを参照してください。

protected boolean inCheck

このフィールドは推奨されなくなり、JDK 内でのこのフィールドの使用はすべて削除されました。inCheck を使う代わりに、checkPermissiondoPrivileged とともに使ってください。

public boolean getInCheck();

このメソッドも推奨されなくなりました。

public SecurityManager();

コンストラクタは、呼び出し元が RuntimePermission("createSecurityManager") アクセス権を持っていると仮定して、複数の SecurityManager の作成が可能になるように修正されました。

protected native Class[] getClassContext();

変更はありません。この呼び出しは、JDK で変更されたメソッド (currentClassLoadercurrentLoadedClassclassLoaderDepthinClassLoader) の 1.1 での動作をエミュレートするために使用できます。

protected ClassLoader currentClassLoader();

JDK 1.1 スタイルのセキュリティマネージャでのこのメソッドの典型的な使用方法は、スタックにクラスローダがあるかどうかを調べることです。このとき、クラスローダがない場合は、コードを「信頼できる」ものとして取り扱い、コードにすべての動作を許可します。このメソッドは JDK で修正され、doPrivileged を呼び出す信頼できる JDK コード (実際には、java.security.AllPermission を与えられたすべてのコード) は、1.1 スタイルのセキュリティマネージャに信頼されるものとして取り扱われるようになりました。またこのコードは、システムクラスローダを無視するように修正されました。システムクラスローダとは、システムクラスローダ (ClassLoader.getSystemClassLoader によって返される) またはその上位オブジェクトのひとつに等しいクラスローダであると定義されます。

このメソッドは、次の 3 つの場合に null コードを返します。

  1. 実行スタック上のすべてのメソッドが、システムクラスローダまたはその上位オブジェクトの 1 つを使って定義されたクラスからのものである場合
  2. 最初の「特権付き」呼び出し元 (java.security.AccessController.doPrivileged を参照) までの実行スタック上のすべてのメソッドが、システムクラスローダまたはその上位オブジェクトの 1 つを使って定義されたクラスからのものである場合
  3. checkPermission を java.security.AllPermission アクセス権で呼び出した結果、SecurityExeception がスローされなかった場合

このメソッドは推奨されなくなりました。代わりに checkPermission を使用してください。

protected Class currentLoadedClass();

このメソッドは currentClassLoader と同様の方法で修正されました。その時点でのセキュリティコンテキストに AllPermission が与えられているか、スタック上のすべてのメソッド (存在する場合は、特権を持つ最初の呼び出し元まで) がシステムクラスローダまたはその上位クラスの 1 つを使って定義されたクラスからのものである場合には、null を返します。

このメソッドは推奨されなくなりました。代わりに checkPermission を使用してください。

protected int classDepth(String name);

動作に変更はありません。このメソッドは推奨されなくなりました。代わりに checkPermission を使用してください。

protected int classLoaderDepth();

このメソッドは currentClassLoader と同様の方法で修正されました。その時点でのセキュリティコンテキストに AllPermission が与えられているか、スタック上のすべてのメソッド (存在する場合は、特権を持つ最初の呼び出し元まで) がシステムクラスローダまたはその祖先の 1 つを使って定義されたクラスからのものである場合には、-1 を返します。

このメソッドは推奨されなくなりました。代わりに checkPermission を使用してください。

protected boolean inClass(String name);

動作に変更はありません。このメソッドは推奨されなくなりました。代わりに checkPermission を使用してください。

protected boolean inClassLoader();

このメソッドは、currentClassLoader が null 以外のクラスローダを返す場合には、true を返します。そのため、このメソッドは currentClassLoader と同じセマンティクスに従います。

このメソッドは推奨されなくなりました。代わりに checkPermission を使用してください。

public Object getSecurityContext();

このメソッドは、java.security.AccessController.getContext への呼び出しとともに作成された java.security.AccessControlContext オブジェクトを返します。JDK 1.1 では、このメソッドはデフォルトで null を返していました。

public void checkPermission(Permission perm);

これは、JDK に新しく追加されたメソッドです。指定されたアクセス権で java.security.AccessController.checkPermission を呼び出します。内部的には、JDK は直接 AccessController を呼び出さずに、常に SecurityManager.checkPermission を呼び出します。このため、プログラマはこのメソッドをオーバーライドして、監査や GUI ダイアログのような機能を追加することができます。

public void checkPermission(Permission perm, Object context);

これは、JDK に新しく追加されたメソッドです。contextAccessControlContext のインスタンスである場合は、AccessControlContext.checkPermission メソッドが、指定されたアクセス権に従って呼び出されます。

contextAccessControlContext のインスタンスでない場合は、SecurityException がスローされます。

public void checkCreateClassLoader();

このメソッドは修正されました。checkPermissionRuntimePermission("createClassLoader") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkCreateClassLoader への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkCreateClassLoader() {
if (someCustomSecurityCheckFails()) {
super.checkCreateClassLoader();
      }
    }
  }

public void checkAccess(Thread t);

スレッドの引数がシステムスレッド (親が null であるスレッドグループに属するスレッド) の場合、このメソッドは RuntimePermission("modifyThread") アクセス権で checkPermission を呼び出します。

より厳しいポリシーが必要なアプリケーションでは、このメソッドをオーバーライドする必要があります。

このメソッドをオーバーライドする場合は、オーバーライド後のメソッドの最初のステートメントで super.checkAccess メソッドを呼び出すか、同様のセキュリティチェックを行う必要があります。

このメソッドをオーバーライドする場合は、オーバーライド後のメソッドでは、呼び出し元のスレッドが RuntimePermission("modifyThread") アクセス権を持つかどうかをチェックして、持っている場合には何もせずに終了するようにします。これは、そのアクセス権を与えられたコード (JDK 自体など) がどんなスレッドでも扱えるようにするためです。

次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkAccess(Thread t) {
// a call to super will throw an exception if someone
// is trying to modify a system thread
super.checkAccess(t);
      ...
if (someCustomSecurityCheckForOtherThreadsFails()) {
// if the check fails, instead of throwing an exception,
// call checkPermission, which will throw an exception
// if need be
checkPermission(new RuntimePermission("modifyThread"));
      }
      ...
    }
  }

public void checkAccess(ThreadGroup g);

スレッドグループの引数がシステムスレッドグループ (親が null) の場合、このメソッドは、RuntimePermission("modifyThreadGroup") アクセス権で checkPermission を呼び出します。

より厳しいポリシーが必要なアプリケーションでは、このメソッドをオーバーライドする必要があります。

このメソッドをオーバーライドする場合は、オーバーライド後のメソッドの最初のステートメントで super.checkAccess メソッドを呼び出すか、同様のセキュリティチェックを行う必要があります。

このメソッドをオーバーライドする場合は、オーバーライド後のメソッドでは、呼び出し元のスレッドが RuntimePermission("modifyThreadGroup") アクセス権を持つかどうかをチェックして、持っている場合には何もせずに終了するようにします。これは、そのアクセス権を与えられたコード (JDK 自体など) がどんなスレッドグループでも扱えるようにするためです。

次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkAccess(ThreadGroup g) {
// a call to super will throw an exception if someone
// is trying to modify the system thread group
super.checkAccess(g);
      ...
if (someCustomSecurityCheckForOtherThreadGroupsFails()) {
// if the check fails, instead of throwing an exception,
// call checkPermission, which will throw an exception
// if need be
checkPermission(new RuntimePermission("modifyThreadGroup"));
      }
      ...
    }
  }

public void checkExit(int status);

このメソッドは修正されました。checkPermissionRuntimePermission("exitVM") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkExit への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkExit(int status) {
if (someCustomSecurityCheckFails()) {
super.checkExit(status);
      }
    }
  }

public void checkExec(String cmd);

このメソッドは修正されました。checkPermissionFilePermission で呼び出します。cmd が絶対パス (java.io.File.isAbsolute を参照) の場合は、FilePermission のターゲットとしてそのまま渡されます。cmd が絶対パスでない場合は、特別なターゲット「<<ALL FILES>>」が使用されます。このターゲットを使用する理由は、個別のプラットフォームで実行されるコマンドの実際のパスを判断するのは、環境変数などの要因のために困難なためです。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkExec への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkExec(String cmd) {
if (someCustomSecurityCheckFails()) {
super.checkExec(cmd);
      }
    }
  }

public void checkLink(String lib);

このメソッドは修正されました。checkPermissionRuntimePermission("loadLibrary."+lib) アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkLink への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkLink(String lib) {
if (someCustomSecurityCheckFails()) {
super.checkLink(lib);
      }
    }
  }

public void checkRead(FileDescriptor fd);

このメソッドは修正されました。checkPermissionRuntimePermission("readFileDescriptor") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkRead への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkRead(FileDescriptor fd) {
if (someCustomSecurityCheckFails()) {
super.checkRead(fd);
      }
    }
  }

public void checkRead(String file);

このメソッドは修正されました。checkPermissionFilePermission(file,"read") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkRead への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkRead(String file) {
if (someCustomSecurityCheckFails()) {
super.checkRead(file);
      }
    }
  }

public void checkRead(String file, Object context);

このメソッドは修正されました。contextAccessControlContext のインスタンスである場合は、AccessControlContext.checkPermission メソッドが、FilePermission(file,"read") のアクセス権に従って呼び出されます。

contextAccessControlContext のインスタンスでない場合は、SecurityException がスローされます。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkRead への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkRead(String file, Object context) {
if (someCustomSecurityCheckFails()) {
super.checkRead(file, context);
      }
    }
  }

public void checkWrite(FileDescriptor fd);

このメソッドは修正されました。checkPermissionRuntimePermission("writeFileDescriptor") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkWrite への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkWrite(FileDescriptor fd) {
if (someCustomSecurityCheckFails()) {
super.checkWrite(fd);
      }
    }
  }

public void checkWrite(String file);

このメソッドは修正されました。checkPermissionFilePermission(file,"write") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkWrite への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkWrite(String file) {
if (someCustomSecurityCheckFails()) {
super.checkWrite(file);
      }
    }
  }

public void checkDelete(String file);

このメソッドは修正されました。checkPermissionFilePermission(file,"delete") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkDelete への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkDelete(String file) {
if (someCustomSecurityCheckFails()) {
super.checkDelete(file);
      }
    }
  }

public void checkConnect(String host, int port);

このメソッドは修正されました。ポートが -1 でない場合には、checkPermissionSocketPermission(host+":"+port,"connect") アクセス権で呼び出します。ポートが -1 の場合は、checkPermissionSocketPermission(host,"resolve") アクセス権で呼び出します。

この動作には JDK 1.1 との一貫性があり、ポートが -1 である場合は、IP アドレスのルックアップが行われていることを示します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkConnect への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkConnect(String host, int port) {
if (someCustomSecurityCheckFails()) {
super.checkConnect(host, port);
      }
    }
  }

public void checkConnect(String host, int port, Object context);

このメソッドは修正されました。contextAccessControlContext のインスタンスである場合は、ポートが -1 に等しくないときには、AccessControlContext.checkPermission メソッドが SocketPermission(host+":"+port,"connect") アクセス権で呼び出されます。ポートが -1 に等しいときは、checkPermissionSocketPermission(host,"resolve") のアクセス権に従って呼び出されます。

contextAccessControlContext のインスタンスでない場合は、SecurityException がスローされます。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkConnect への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkConnect(String host, int port, Object context) {
if (someCustomSecurityCheckFails()) {
super.checkConnect(host, port, context);
      }
    }
  }

public void checkListen(int port)

このメソッドは修正されました。ポートが 0 でない場合は、checkPermissionSocketPermission("localhost:"+port,"listen") で呼び出します。ポートが 0 の場合は、checkPermissionSocketPermission("localhost:1024-","listen") で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkListen への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkListen(int port) {
if (someCustomSecurityCheckFails()) {
super.checkListen(port);
      }
    }
  }

public void checkAccept(String host, int port);

このメソッドは修正されました。checkPermissionSocketPermission(host+":"+port,"accept") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkAccept への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkAccept(String host, int port) {
if (someCustomSecurityCheckFails()) {
super.checkAccept(host, port);
      }
    }
  }

public void checkMulticast(InetAddress maddr);

このメソッドは修正されました。checkPermissionSocketPermission(maddr.getHostAddress(),"accept,connect") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkMulticast への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkMultiCast(InetAddress maddr) {
if (someCustomSecurityCheckFails()) {
super.checkMultiCast(maddr);
      }
    }
  }

public void checkMulticast(InetAddress maddr, byte ttl);

このメソッドは修正されました。checkPermissionSocketPermission(maddr.getHostAddress(),"accept,connect") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkMulticast への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkMultiCast(InetAddress maddr, byte ttl) {
if (someCustomSecurityCheckFails()) {
super.checkMultiCast(maddr, ttl);
      }
    }
  }

public void checkPropertiesAccess();

このメソッドは修正されました。checkPermissionPropertyPermission("*", "read,write") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkPropertiesAccess への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkPropertiesAccess() {
if (someCustomSecurityCheckFails()) {
super.checkPropertiesAccess();
      }
    }
  }

public void checkPropertyAccess(String key);

このメソッドは修正されました。checkPermissionPropertyPermission(key, "read") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkPropertyAccess への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkPropertyAccess(String key) {
if (someCustomSecurityCheckFails()) {
super.checkPropertiesAccess(key);
      }
    }
  }

public boolean checkTopLevelWindow(Object window);

このメソッドは修正されました。checkPermissionAWTPermission("showWindowWithoutWarningBanner") アクセス権で呼び出し、SecurityException がスローされない場合は true を返します。それ以外の場合は false を返します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常 false を返す位置で、super.checkTopLevelWindow への呼び出しを行い、super.checkTopLevelWindow の値を返す必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkTopLevelWindow(Object window) {
if (someCustomSecurityCheckFails()) {
return super.checkTopLevelWindow(window);
} else {
return true;
      }
    }
  }

public void checkPrintJobAccess();

このメソッドは修正されました。checkPermissionRuntimePermission("queuePrintJob") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkPrintJobAccess への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkPrintJobAccess() {
if (someCustomSecurityCheckFails()) {
super.checkPrintJobAccess();
      }
    }
  }

public void checkSystemClipboardAccess();

このメソッドは修正されました。checkPermissionAWTPermission("accessClipboard") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkSystemClipboardAccess への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkSystemClipboardAccess() {
if (someCustomSecurityCheckFails()) {
super.checkSystemClipboardAccess();
      }
    }
  }

public void checkAwtEventQueueAccess();

このメソッドは修正されました。checkPermissionAWTPermission("accessEventQueue") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkAwtEventQueueAccess への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkAwtEventQueueAccess() {
if (someCustomSecurityCheckFails()) {
super.checkAwtEventQueueAccess();
      }
    }
  }

public void checkPackageAccess(String pkg);

このメソッドは修正されました。最初に、java.security.Security.getProperty("package.access") を呼び出してコンマで区切られたリストを取得することにより、制限付きのパッケージのリストを得ます。次に、pkg が制限付きパッケージのどれかで開始するかどうか、または等しいかどうかをチェックします。該当する場合には、checkPermissionRuntimePermission("accessClassInPackage."+pkg) アクセス権で呼び出されます。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドの 1 行目で、super.checkPackageAccess への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkPackageAccess(String pkg) {
super.checkPackageAccess(pkg);
      ...
someCustomSecurityCheck();
      ...
    }
  }

public void checkPackageDefinition(String pkg);

このメソッドは修正されました。最初に、java.security.Security.getProperty("package.definition") を呼び出してコンマで区切られたリストを取得することにより、制限付きのパッケージのリストを得ます。次に、pkg が制限付きパッケージのどれかで開始するかどうか、または等しいかどうかをチェックします。該当する場合には、checkPermissionRuntimePermission("defineClassInPackage."+pkg) アクセス権で呼び出されます。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドの 1 行目で、super.checkPackageDefinition への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkPackageDefinition(String pkg) {
super.checkPackageDefinition(pkg);
      ...
someCustomSecurityCheck();
      ...
    }
  }

public void checkSetFactory();

このメソッドは修正されました。checkPermissionRuntimePermission("setFactory") アクセス権で呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkSetFactory への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkSetFactory() {
if (someCustomSecurityCheckFails()) {
super.checkSetFactory();
      }
    }
  }

public void checkMemberAccess(Class clazz, int which);

このメソッドは修正されました。デフォルトのポリシーは PUBLIC メンバへのアクセスおよび、呼び出し元と同じクラスローダを持つクラスへのアクセスを許可します。それ以外の場合はすべて、checkPermissionRuntimePermission("accessDeclaredMembers") アクセス権で呼び出されます。

このメソッドをオーバーライドする場合は、super.checkMemberAccess への呼び出しは行えません。checkMemberAccess のデフォルト実装は、スタック深度 4 にあることをチェックされるコードに依存します。次に例を示します。

someCaller[3]
java.lang.Class.someReflectionAPI [2]
java.lang.Class.checkMemberAccess [1]
SecurityManager.checkMemberAccess [0]
この動作をエミュレートするには、getClassContext を呼び出し、デフォルトの checkMemberAccess メソッドの場合と同様に、インデックス 3 のクラスのクラスローダを調べる必要があります。
if (which != Member.PUBLIC) {
Class stack[] = getClassContext();
    /*
* stack depth of 4 should be the caller of one of the
* methods in java.lang.Class that invoke checkMember
* access.The stack should look like:
     * 
* someCaller [3]
* java.lang.Class.someReflectionAPI  [2]
* java.lang.Class.checkMemberAccess [1]
* MySecurityManager.checkMemberAccess [0]
     *
     */
if ((stack.length<4) ||
(stack[3].getClassLoader() != clazz.getClassLoader())) {
if (checkMemberAccessPermission == null)
checkMemberAccessPermission =
new RuntimePermission("accessDeclaredMembers");
checkPermission(checkMemberAccessPermission);
    }
  }

このメソッドは、JDK で現在でも呼び出し元の深度に基づいている唯一のセキュリティマネージャメソッドです。このメソッドが存在する理由は、呼び出し元が、自分と同じクラスローダからのクラスに反映できるようにするためです。

public void checkSecurityAccess(String target);

このメソッドは修正されました。指定されたアクセス権ターゲット名に対する SecurityPermission オブジェクトを作成し、そのアクセス権で checkPermission を呼び出します。

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドが通常は例外をスローする位置で、super.checkSecurityAccess への呼び出しを行う必要があります。次に例を示します。

public class MySecurityManager extends SecurityManager {

public void checkSecurityAccess(String target) {
if (someCustomSecurityCheckFails()) {
super.checkSecurityAccess(target);
      }
    }
  }

public ThreadGroup getThreadGroup();

このメソッドは修正されていません。


Copyright © 1997-2001 Sun Microsystems, Inc.All Rights Reserved.

コメントの送付先: java-security@sun.com。これは購読リストではありません。
Sun
Java ソフトウェア