Previous | Next | Trail Map | Custom Networking and Security | 自前のセキュリティマネージャを用意する


セキュリティマネージャを書く

自前のセキュリティマネージャを書くには、SecurityManager クラスのサブクラスを 作成しなければならない。 SecurityManager サブクラスは SecurityManager のさま ざまなメソッドを上書きして、ユーザの Java アプリケーションに必要な検査と許可をカスタマイズする。

このページでは、ファイルシステムの読み書きに制限を課すセキュリティマネージャ の例を丹念に解説する。セキュリティマネージャから許可を得るため、読み取りのた めにファイルを開くメソッドは SecurityManager の checkRead() メ ソッドの 1 つを起動する。同様に、書き込みのためにファイルを開くメソッドは SecurityManager の checkWrite() メソッドの 1 つを起動する。セキ ュリティマネージャがその操作を許可すれば checkXXX() メ ソッドは戻り、そうでなければ checkXXX() は SecurityException をあげる。

ファイルシステムのアクセス方針をより厳しくするため、ここで紹介する SecurityManager サブクラスの例は、 SecurityManager の checkRead()checkWrite() メソッドを上書きする。SecurityManager は checkRead() の 3 つのバージョンと checkWrite() の 2 つのバージョンを用意している。このようなバージョンはそれぞれ、アプリケーシ ョンがファイルを I/O のために開くことを許可されているかどうかを検査するよう になっている。 ブラウザがよく実装しているセキュリティ方針では、ネットワークを通じてロードさ れたアプレットは、ユーザが許可しないかぎり、ローカルファイルシステムを読み書きできないようになっている。

ここで紹介する例が実装している方針では、アプリケーションが読み書きのためにフ ァイルを開こうとすると、ユーザにパスワード入力を求めるプロンプトを表示する。 パスワードが正しければ、アクセスが許される。

すべてのセキュリティマネージャは SecurityManager のサブクラスでなければなら ない。したがって、ここで紹介する PasswordSecurityManager クラスは SecurityManager を拡張したものである。

class PasswordSecurityManager extends SecurityManager {
    . . .
}

次に、PasswordSecurityManager は限定されたファイルシステムアクセスを行えるよ うにするためユーザが入力しなければならないパスワードを納めた、プライベイトなインスタンス変数 password を宣言する。この password は次のような 構文で設定される。

PasswordSecurityManager(String password) {
    super();
    this.password = password;
}

PasswordSecurityManager クラスでの次のメソッドは、accessOK() と いう名前のプライベイトなヘルパメソッドである。 このメソッドはユーザにパスワ ード入力のプロンプトを表示し、正しいかどうか検査する。ユーザが正しいパスワー ドを入力した場合は、このメソッドは true を返し、そうでない場合は false を返 す。

private boolean accessOK() {
    int c;
    DataInputStream dis = new DataInputStream(System.in);
    String response;

    System.out.println("What's the secret password?");
    try {
        response = dis.readLine();
        if (response.equals(password))
            return true;
        else
            return false;
    } catch (IOException e) {
        return false;
    }
}

最後に、PasswordSecurityManager クラスの末尾にあるのは、上書きされた 3 つの checkRead() メソッドと 2 つの checkWrite() メソッ ドである。

public void checkRead(FileDescriptor filedescriptor) {
    if (!accessOK())
        throw new SecurityException("Not a Chance!");
}
public void checkRead(String filename) {
    if (!accessOK())
        throw new SecurityException("No Way!");
}
public void checkRead(String filename, Object executionContext) {
    if (!accessOK())
        throw new SecurityException("Forget It!");
}
public void checkWrite(FileDescriptor filedescriptor) {
    if (!accessOK())
        throw new SecurityException("Not!");
}
public void checkWrite(String filename) {
    if (!accessOK())
        throw new SecurityException("Not Even!");
}

すべての checkXXX() メソッドは accessOK を呼び出し、ユーザにパスワード入力のプロンプトを表示する。 アクセスが許可されない 場合は、checkXXX() は SecurityException をあげる。許可される場合は checkXXX() は普通に戻ってくる。SecurityException は実 行時例外であり、これ自体をメソッドの throws 節で宣言する必要は ない。

checkRead()checkWrite() は、種々の操作を検証す る SecurityManager の多数の checkXXX() メソッドのほん の一部にすぎない。自分独自のセキュリティ方針を実装するために、 checkXXX() メソッドを上書きしたり、いくつでも追加した りすることができる。SecurityManager の checkXXX() メソ ッドのすべてを上書きする必要はなく、カスタマイズすべきメソッドだけでよい。し かし、すべての checkXXX() メソッドに対して SecurityManager クラスが提供するデフォルトの実装は SecurityException をあげ る。 言い換えると、SecurityManager クラスはデフォルトではセキュリティ制限の支配下 にあるすべての操作を拒絶する。したがって、望みの振る舞いを得るには、 SecurityManager の 多数の checkXXX() メソッドを上書きしなければならないということになる。

SecurityManager の checkXXX() メソッドの動作はすべて同じである。

読者が上書きされた checkXXX() メソッドを実装する場合、 上記の方式に従うようにする。

これが、我々の SecurityManager サブクラスのすべてである。見てきてわかるよう に、SecurityManager を実装することは簡単である。ユーザは以下のように実装するだけである。

慎重を要する部分は、どのメソッドを上書きするかを判別して、自分のセキュリティ 方針を実現することである。 保護したい操作の種類に応じてどのメソッドを上書きすべきかについては、上書きする SecurityManager のメソッドを決定する を参照 する。 次のページ では、Java アプリケーションの実際 に機能するセキュリティマネージャとして PasswordSecurityManager クラスをイン ストールする方法を示す。

参照

java.lang.SecurityManager
java.lang.SecurityException


Previous | Next | Trail Map | Custom Networking and Security | 自前のセキュリティマネージャを用意する