セキュリティーマネージャーと Java SE JDK




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


はじめに

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

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

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

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

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

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

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

SecurityManager クラスには、名前が check で始まるメソッドが多数あります。たとえば、checkReadcheckConnect などです。Java ライブラリのさまざまなメソッドが、セキュリティーが重視されるオペレーションを実行する前に毎回 check メソッドを呼び出します。これにより、セキュリティーマネージャーには、例外をスローしてオペレーションの実行を阻止する機会が与えられます。セキュリティーマネージャールーチンは、操作が許可される場合は何も行わずに復帰します。操作が許可されない場合は SecurityException をスローします。ただし、checkTopLevelWindow はこうした規約の唯一の例外で、boolean 値を返します。

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 コードはアプレットから呼び出された場合にも、クラスローダーを作成することができます。その理由は、使用されるのはクラスローダーを持つクラスの深度であり、それが存在するという事実ではないからです。

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

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 スタイルのセキュリティーマネージャーが動作するように変更されました。

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

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

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

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

    システムクラスローダーによってロードされたクラスには、アプリケーションクラス (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 メソッドは、checkPermissionjava.util.PropertyPermission アクセス権で呼び出します。

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 によって返される) またはその祖先の 1 つに等しいクラスローダーであると定義されます。

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

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

このメソッドは非推奨になりました。代わりに 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 を呼び出します。

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

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドの 1 番目の文で 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 を呼び出します。

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

このメソッドをオーバーライドする場合は、オーバーライドされたメソッドの 1 番目の文で 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 © 1993, 2013, Oracle and/or its affiliates. All rights reserved.