【Java 技术专题】「盲点追踪」突破知识盲点分析 Java 安全管理器(SecurityManager)
前提介绍
Java 安全应该包括两方面的内容,一是 Java 平台(即是 Java 运行环境)的安全性;二是 Java 语言开发的应用程序的安全性。由于我们不是 Java 本身语言的制定开发者,所以第一个安全性不需要我们考虑。其中第二个安全性是我们重点考虑的问题,一般我们可以通过安全管理器机制来完善安全性,安全管理器是安全的实施者,可对此类进行扩展,它提供了加在应用程序上的安全措施,通过配置安全策略文件达到对网络、本地文件和程序其它部分的访问限制的效果。
安全管理器的作用
当 Java 应用程序运行时,它们可以访问计算机上的资源,例如文件系统、网络、系统属性等。SecurityManager 是 Java 中的一个类,它允许开发人员控制应用程序对这些资源的访问。SecurityManager 可以实现以下功能:
安全策略管理:SecurityManager 可以实现安全策略管理,以确保应用程序只能访问它们被授权访问的资源。
访问控制:SecurityManager 可以实现访问控制,以确保应用程序只能访问它们被授权访问的资源。
权限管理:SecurityManager 可以实现权限管理,以确保应用程序只能执行它们被授权执行的操作。
安全审计:SecurityManager 可以实现安全审计,以记录应用程序对资源的访问和操作。
在 Java 中,可以通过 System.setSecurityManager()方法来设置 SecurityManager。开发人员可以编写自己的 SecurityManager 类,以实现自定义的安全策略管理、访问控制、权限管理和安全审计功能。
安全管理机制
上图展示了安全管理器的工作机制,当运行 Java 程序时,安全管理器会根据 policy 文件所描述的策略给程序不同模块分配权限,假设把应用程序分成了三块,每块都有不同的权限,第一块有读取某文件的权限,第二块同时拥有读取某文件跟内存的权限,第三块有监听 socket 的权限。通过这个机制就能很好地控制程序各个部分的各种操作权限,从应用层上为我们提供了安全管理策略。
检查操作权限
上图为安全管理器对文件操作进行管理的工作过程,当应用程序要读取本地文件时,securitymanager 就会在读取前进行拦截,判断是否有读取此文件的权限,如果有则顺利读取,否则将抛出访问异常。SecurityManager 类中提供了很多检查权限的方法,例如 checkPermission 方法会根据安全策略文件描述的权限对操作进行判断是否有操作权限,而 checkRead 方法则用于判断对文件访问权限。一旦发现没有权限都会抛出安全异常。
开启安全管理器
一般而言,Java 程序启动时并不会自动启动安全管理器,可以通过以下两种方法启动安全管理器:
一种是隐式,启动默认的安全管理器最简单的方法就是:直接在启动命令中添加-Djava.security.manager 参数即可。
一种是显式,实例化一个 java.lang.SecurityManager 或继承它的子类的对象,然后通过 System.setSecurityManager()来设置并启动一个安全管理器。
在启动安全管理器时可以通过-Djava.security.policy 选项来指定安全策略文件。如果没有指定策略文件的路径,那么安全管理器将使用默认的安全策略文件,它位于 %JAVA_HOME%/jre/lib/security 目录下面的 java.policy。需要说明一下的是,=表示这个策略文件将和默认的策略文件一同发挥作用;==表示只使用这个策略文件。
policy 文件包含了多个 grant 语句,每一个 grant 描述某些代码拥有某些操作的权限。在启动安全管理器时会根据 policy 文件生成一个 Policy 对象,任何时候一个应用程序只能有一个 Policy 对象。
那么如何才能实现自己的安全管理器,并且配置权限呢?下面将通过一个简单的例子阐明实现步骤,一般可以分为以下两步:
创建一个 SecurityManager 子类,并根据需要重写一些方法。
根据应用程序代码的权限需要配置策略文件。如果使用默认安全管理器则省略第一步,下面用个例子说明安全管理器的使用:
分下面几种情况运行程序:
假如不添加启动参数直接运行,则相当于没有启动安全管理器,SecurityManager 打印出来为 null,且能正确读取 protect.txt 文件跟 file.encoding 属性。
添加启动参数-Djava.security.manager-Djava.security.policy=c:/protect.policy,俩参数分别代表启动默认安全管理器和指明策略配置文件路径。此时 SecurityManager 打印出来为不为 null,但由于此时 protect.policy 里面并没有做任何授权,所以在读取文件的时就抛出 AccessControlExcepti on 异常。
在 protect.policy 文件添加以下授权语句,
此时 SecurityManager 不为空,并且有权限读取 protect.txt 文件,但最终还是会抛一个 AccessControlException 异常,因为并没有权限读取 file.encoding 系统属性。
将 protect.policy 授权语句改为如下:
这次读取文件跟读取系统属性的权限都有了,程序正常运行,不再抛出安全异常。由上面几种情况我们清晰了解安全管理器的使用,通过简单地配置策略文件能达到应用安全的管理。Java 的 Permission 类是用来定义类所拥有的权限,Java 本身包括了一些 Permission 类,如下:
版权声明: 本文为 InfoQ 作者【洛神灬殇】的原创文章。
原文链接:【http://xie.infoq.cn/article/b6a7e074f24caebc3744a001e】。文章转载请联系作者。
评论