Intro to the Java SecurityManager – Java SecurityManager的介绍

最后修改: 2019年 10月 7日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll have a look into Java’s built-in security infrastructure, which is disabled by default. Specifically, we’ll examine its main components, extension points, and configurations.

在本教程中,我们将对Java的内置安全基础设施进行考察,它在默认情况下是禁用的。具体来说,我们将研究其主要组件、扩展点和配置。

2. SecurityManager in Action

2.SecurityManager在行动

It might be a surprise, but default SecurityManager settings disallow many standard operations:

这可能是一个惊喜,但默认的SecurityManager设置不允许许多标准操作

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

Here, we programmatically enable security supervision with default settings and attempt to connect to google.com.

在这里,我们以编程方式启用默认设置的安全监督,并尝试连接到google.com。

Then we get the following exception:

然后我们得到了以下异常。

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

There are numerous other use-cases in the standard library — for example, reading system properties, reading environment variables, opening a file, reflection, and changing the locale, to name a few.

在标准库中还有许多其他的用例–例如,读取系统属性、读取环境变量、打开文件、反射和改变区域设置,仅举几例。

3. Use-Case

3.用例

This security infrastructure has been available since Java 1.0. This was a time where applets – Java applications embedded into the browser – were pretty common. Naturally, it was necessary to constrain their access to system resources.

这种安全基础设施从Java 1.0开始就已经存在了。那时候,小程序–嵌入到浏览器中的Java应用程序–是非常普遍的。自然,有必要限制它们对系统资源的访问。

Nowadays, applets are obsolete. However, security enforcement is still an actual concept when there is a situation in which third-party code executes in a protected environment.

如今,小程序已经过时了。然而,当出现第三方代码在受保护环境中执行的情况时,安全执行仍然是一个实际的概念

For example, consider that we have a Tomcat instance where third-party clients may host their web applications. We don’t want to allow them to execute operations like System.exit() because that would affect other applications and possibly the whole environment.

例如,考虑到我们有一个Tomcat实例,第三方客户可能在那里托管他们的Web应用程序。我们不想让他们执行像System.exit()这样的操作,因为这将影响其他应用程序,甚至可能影响整个环境。

4. Design

4.设计

4.1. SecurityManager

4.1.SecurityManager

One of the main components in the built-in security infrastructure is java.lang SecurityManager. It has several checkXxx methods like checkConnect, which was authorizing our attempt to connect to Google in the test above. All of them delegates to the checkPermission(java.security.Permission) method.

内置安全基础设施的主要组件之一是java.lang SecurityManager。它有几个checkXxx方法,比如checkConnect,它在上面的测试中授权我们尝试连接到Google。所有这些都委托给checkPermission(java.security.Permission)方法。

4.2. Permission

4.2.许可

java.security.Permission instances stand for authorization requests. Standard JDK classes create them for all potentially dangerous operations (like reading/writing a file, opening a socket, etc.) and give them over to SecurityManager for proper authorization.

java.security.Permission实例代表授权请求。标准 JDK 类为所有潜在的危险操作(如读/写文件、打开套接字等)创建这些实例,并将其交给 SecurityManager 进行适当的授权。

4.3. Configuration

4.3.配置

We define permissions in a special policy format. These permissions take the form of grant entries:

我们以一种特殊的策略格式定义权限。这些权限采取grant条目的形式。

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

The codeBase rule above is optional. We can specify no field at all there or use signedBy (integrated with corresponding certificates in the keystore) or principal (java.security.Principal attached to the current thread via javax.security.auth.Subject). We can use any combination of those rules.

上面的codeBase规则是可选的。我们可以不在这里指定任何字段,或者使用signedBy(与keystore中的相应证书集成)或principal(通过javax.security.auth.Subject附加到当前线程的java.security.Principal)。我们可以使用这些规则的任何组合

By default, the JVM loads the common system policy file located at <java.home>/lib/security/java.policy. If we’ve defined any user-local policy in  <user.home>/.java.policy, the JVM appends it to the system policy.

默认情况下,JVM会加载位于<java.home>/lib/security/java.policy的通用系统策略文件。如果我们在<user.home>/.java.policy中定义了任何用户本地策略,JVM会将其附加到系统策略中。

It’s also possible to specify policy file via command line: –Djava.security.policy=/my/policy-file. That way we can append policies to the previously loaded system and user policies.

也可以通过命令行指定策略文件:-Djava.security.policy=/my/policy-file。这样我们就可以将策略附加到之前加载的系统和用户策略上。

There is a special syntax for replacing all system and user policies (if any) – double equals sign: –Djava.security.policy==/my/policy-file

有一种特殊的语法用于替换所有系统和用户策略(如果有的话)–双等号:-Djava.security.policy==/my/policy-file

5. Example

5.例子

Let’s define a custom permission:

我们来定义一个自定义权限。

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

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

and a shared service that should be protected:

和一项应该受到保护的共享服务。

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");
    }
}

If we try to run it with a security manager enabled, an exception is thrown:

如果我们试图在启用安全管理器的情况下运行它,就会抛出一个异常。

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)

We can create our <user.home>/.java.policy file with the following content and try re-running the application:

我们可以用以下内容创建我们的<user.home>/.java.policy文件,并尝试重新运行应用程序。

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

It works just fine now.

它现在工作得很好。

6. Conclusion

6.结论

In this article, we checked how the built-in JDK security system is organized and how we can extend it. Even though the target use-case is relatively rare, it’s good to be aware of it.

在这篇文章中,我们检查了内置的JDK安全系统是如何组织的,以及我们可以如何扩展它。尽管目标用例相对较少,但了解一下还是有好处的。

As usual, the complete source code for this article is available over on GitHub.

像往常一样,本文的完整源代码可在GitHub上获得