使用 SecurityManager 和 Policy File 管理 Java 程序的权限
Posted on 2016-08-04 15:48 京山游侠 阅读(3439) 评论(2) 编辑 收藏 举报参考资料##
该文中的内容来源于 Oracle 的官方文档。Oracle 在 Java 方面的文档是非常完善的。对 Java 8 感兴趣的朋友,可以从这个总入口 Java SE 8 Documentation 开始寻找感兴趣的内容。本博客不定期从 Oracle 官网搬砖。
前言##
Java 在 Security 方面的特性,总是被很多人当做宣传的重点,但是对我而言,这基本上是八百年都用不到一次的特性。可是没办法,为了知识体系的完整性,我也不得不硬着头皮学习这些八竿子都打不着的内容。
很多 Java 程序默认在一个安全的环境中运行,比如 Applet程序。当这些在安全环境中运行的程序需要访问我们系统中的资源时,就会受到限制。换句话说,就是当 Applet 之类的程序运行时,默认就会启动一个 SecurityManager,SecurityManager 负责检查该程序是否具有相应的权限。但是很多 Java 程序不会默认启动 SecurityManager,比如大部分在我们系统中直接运行的 Java 程序。没有启用 SecurityManager 的程序的权限不会受到限制,如果存在恶意代码的话,就会产生安全问题。如果我们非要放宽对它们的限制的话,就需要对相应的 Java 程序进行授权,授权需要用到 Policy File。
没有启用 SecurityManager 的程序可以访问系统中的任意资源##
废话少说,直接开始实战。先看两个示例程序,GetProps.java
和 Count.java
,它们一个需要访问 Java 运行环境中的 Properties,一个需要读取磁盘上的文件。代码如下图:
编译、打包、运行,这两个程序的运行结果非常符合预期,如下图:
从上图中可以看出,我在打包的时候没有使用 jar
的 -e
选项指定程序的入口点,只是简单的把所有的 .class
打成一个 jar 包而已。运行的时候使用 java -cp HelloWorld.jar
将该 jar 包指定为 CLASSPATH 并直接运行其中的类。其实这里的程序不打包也可以运行,但是要对程序进行签名,就必须得打包了。
启用了 SecurityManager 的程序权限会被限制##
如果启用 SecurityManager,则程序的权限会受到限制。怎么启用 SecurityManager 呢?有两个办法,一个办法是在启动程序的使用使用 java -Djava.security.manager
选项,另一个办法是在代码中使用 System.setSecurityManager(new SecurityManager());
。先看下图,使用第一种办法开启 SecurityManager:
可以看到,一旦使用 java -Djava.security.manager
选项启动,程序 GetProps
和 Count
都产生了异常。我们也可以在代码中启用 SecurityManager,也可以手动调用 SecurityManager 的方法来验证运行的程序是否具有相应的权限。请看下图示例程序 SecurityOnByCode.java
:
编译、打包、运行,果然产生了异常,如下图:
使用 Policy File 为程序授权##
如果要让启用了 SecurityManager 的程序正常运行,就必须对它们进行相应的授权。在本例中,需要对 GetProps
和 SecurityOnByCode
示例程序授予它访问 System Properties 的权限,为 Count
示例程序授予访问目录 src/com/xkland/sample
中文件的权限。授权是使用 Policy File 来控制的。系统中有一个全局的 Policy File,它的路径是 ${java.home}/lib/security/java.policy
,另外还可以为当前用户定义一个用户级别的 Policy File,只要这个文件的路径是 ${user.home}/.java.policy
就行。也可以编写其它的任意的 Policy File,只需要在启动程序的时候用 java -Djava.security.policy=
选项指定 Policy File 的路径即可。
在 JDK 提供的工具中,有一个 policytool,这是一个 GUI 程序,它可以极大地简化我们编写 Policy File 的过程,后面的实战中会用到它。首先,先来为需要访问 System Properties 的程序授权,我制定一个这样的策略:位于 ${user.home}/HelloJavaWorld
目录下的程序可以访问 System Properties,这就需要用到基于 CodeBase 的授权。在本例中,我使用 policytool
创建一个 youxia.policy
文件,并基于 CodeBase 授予相应的访问 System Properties 的 java.util.PropertyPermission
,如下图:
可以使用 cat youxia.policy
命令查看生成的 Policy File 的内容。授权之后再运行 GetProps
程序和 SecurityOnByCode
程序,发现它们都能顺利运行,没有产生任何异常,如下图:
但是另外一个程序 Count
仍然受限的,因为我们没有给它授予访问文件的权限。下面来解决这个问题,我设计的策略是如果该程序是被 youxia 的证书签名的,则授予它访问 src/com/xkland/sample
目录下所有文件的权利。这就需要用到基于 SignedBy 的授权。使用该类型的授权必须先指定密钥库(keystore),而密钥库的类型、供应方和口令是可以留空的,如下图:
然后再添加相应的授权,如下图:
最后来看运行效果。先常规使用 cat youxia.policy
看看,发现 Policy File 中多了一个 Grant SignedBy "youxia"
的条目,然后对 HelloWorld.jar
使用 youxia 的证书进行签名,最后运行程序,结果一切正常。如下图:
总结##
Java 领域中一些关于安全的特性往往是商家宣传的重点,但是对于我们普通开发者而言,用到这些特性的机会很少,因此往往会比较陌生。关于证书和密钥库的内容,请看这里 JDK中的证书生成和管理工具keytool, 关于 jar 文件签名和验证的内容,请看这里 Java程序的打包、签名和验证。这一篇中涉及到的 SecurityManager 和 Policy File 本身并不难,按我这个实战的流程走一遍即可了然于胸。