1. 概要

このチュートリアルでは、デフォルトで無効になっているJavaの組み込みのセキュリティインフラストラクチャについて説明します。 具体的には、その主要なコンポーネント、拡張ポイント、および構成を調べます。

2. SecurityManagerの動作

意外かもしれませんが、デフォルトのSecurityManager設定では多くの標準操作が許可されていません。

System.setSecurityManager(new SecurityManager());
new URL("http://www.google.com").openConnection().connect();

ここでは、デフォルト設定でセキュリティ監視をプログラムで有効にし、google.comへの接続を試みます。

次に、次の例外が発生します。

java.security.AccessControlException: access denied ("java.net.SocketPermission"
  "www.google.com:80" "connect,resolve")

標準ライブラリには、他にも多くのユースケースがあります。たとえば、システムプロパティの読み取り、環境変数の読み取り、ファイルのオープン、リフレクション、ロケールの変更などです。

3. 使用事例

このセキュリティインフラストラクチャは、Java1.0以降で使用できます。 これは、アプレット(ブラウザに埋め込まれたJavaアプリケーション)がかなり一般的だった時代でした。 当然、システムリソースへのアクセスを制限する必要がありました。

現在、アプレットは廃止されています。 ただし、保護された環境でサードパーティのコードが実行される状況がある場合、セキュリティの実施は依然として実際の概念です

たとえば、サードパーティのクライアントがWebアプリケーションをホストする可能性のあるTomcatインスタンスがあるとします。 System.exit()のような操作は、他のアプリケーションや環境全体に影響を与える可能性があるため、実行を許可したくありません。

4. デザイン

4.1. 保安管理者

組み込みのセキュリティインフラストラクチャの主要コンポーネントの1つは、 java.langSecurityManagerです。 上記のテストでGoogleに接続する試みを承認したcheckConnectのようないくつかのcheckXxxメソッドがあります。 それらはすべて、 checkPermission(java.security.Permission)メソッドに委任します。

4.2. 許可

java.security.Permission インスタンスは、承認要求を表します。 標準のJDKクラスは、潜在的に危険なすべての操作(ファイルの読み取り/書き込み、ソケットのオープンなど)のためにそれらを作成し、適切な承認のためにSecurityManagerに渡します。

4.3. 構成

パーミッションは特別なポリシー形式で定義します。 これらの権限は、grantエントリの形式を取ります。

grant codeBase "file:${{java.ext.dirs}}/*" {
    permission java.security.AllPermission;
};

上記のcodeBaseルールはオプションです。 そこにフィールドをまったく指定しないか、 signedBy (キーストア内の対応する証明書と統合)またはプリンシパルjava.security.Principalを現在に接続して使用することができます javax.security.auth.Subject を介したスレッド)。 これらのルールの任意の組み合わせを使用できます

デフォルトでは、JVMは<にある共通システムポリシーファイルをロードします。 java.home> /lib/security/java.policy 。 でユーザーローカルポリシーを定義した場合 /.java.policy 、JVMはそれをシステムポリシーに追加します。

コマンドラインからポリシーファイルを指定することもできます:– Djava.security.policy = / my /policy-file。 このようにして、以前にロードされたシステムおよびユーザーポリシーにポリシーを追加できます。

すべてのシステムおよびユーザーポリシー(存在する場合)を置き換えるための特別な構文があります– double equals sign:– Djava.security.policy == / my / policy-file

5. 例

カスタム権限を定義しましょう:

public class CustomPermission extends BasicPermission {
    public CustomPermission(String name) {
        super(name);
    }

    public CustomPermission(String name, String actions) {
        super(name, actions);
    }
}

保護する必要のある共有サービス:

public class Service {

    public static final String OPERATION = "my-operation";

    public void operation() {
        SecurityManager securityManager = System.getSecurityManager();
        if (securityManager != null) {
            securityManager.checkPermission(new CustomPermission(OPERATION));
        }
        System.out.println("Operation is executed");
    }
}

セキュリティマネージャを有効にして実行しようとすると、例外がスローされます。

java.security.AccessControlException: access denied
  ("com.baeldung.security.manager.CustomPermission" "my-operation")

    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
    at java.security.AccessController.checkPermission(AccessController.java:884)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
    at com.baeldung.security.manager.Service.operation(Service.java:10)

私たちは私たちを作成することができます /.java.policy 次の内容のファイルを作成して、アプリケーションを再実行してみてください。

grant codeBase "file:<our-code-source>" {
    permission com.baeldung.security.manager.CustomPermission "my-operation";
};

今は問題なく動作します。

6. 結論

この記事では、組み込みのJDKセキュリティシステムがどのように構成され、どのように拡張できるかを確認しました。 ターゲットのユースケースは比較的まれですが、それを知っておくのは良いことです。

いつものように、この記事の完全なソースコードは、GitHubから入手できます。