JDK源码分析——SecurityManager安全管理器实例分析

M君 4月前 ⋅ 536 阅读

本篇文章中的源码可以从我的github上下载:

https://github.com/mh47838704/JavaExample

源码在Test包下的:

package com.mh.JavaExample.sm;

* The security manager is a class that allows
* applications to implement a security policy. It allows an
* application to determine, before performing a possibly unsafe or
* sensitive operation, what the operation is and whether
* it is being attempted in a security context that allows the
* operation to be performed. The
* application can allow or disallow the operation.

上面是摘自安全管理器的介绍:Java安全管理器允许应用程序设置一个安全管理策略,通过安全管理策略实现对应用程序中的敏感的操作的管理(运行或者是禁制)。

1、在Java中应用程序启动的时候是默认没有设置安全管理器的,可以通过下面的代码观察,下面的代码在常规的启动的时候会输出null

System.out.println("系统当前的安全管理器:"+System.getSecurityManager());

2、在Java中可以通过配置启用jdk中默认的安全管理器,然后再使用上面的代码调试,那么会显示相应的实例,而不是null

VM options: -Djava.security.manager

3、在最前面说到了可以配置策略,那么策略到底是一个什么样的文件呢?既然在java中有默认的安全管理器,那么是不是也意味着有默认的策略配置文件呢?当然有,后面会对文件中的内容进行解释

JDK\jre\lib\security\java.policy

4、问题又来了,当默认的策略不能满足我们的需求的时候怎么办呢?当然是自定义策略配置文件了,格式参考java.policy即可。那么如何使得我们的默认安全管理器加载呢?,使用如下启动命令参数即可(注意:一个等号“=”代表自定义策略文件和默认策略文件java.policy共同生效,两个等号“==”表示只有自定义策略文件生效):

-Djava.security.policy="...\JavaExample\src\test\resources\conf\sjava.policy"

 

总一:上面基本上对什么是安全管理器、策略配置文件、启动安全管理器、启用自定义配置文件等进行了大致的介绍,下面将通过一个实例进行实战来加深对这些概念的理,具体的实例代码如下:

实例的目录结构:

package com.mh.JavaExample.sm;

import org.junit.Test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

/**
* 安全管理器测试类
* ==========================
* 1 首先创建test文件
* 1.1 运行该测试,System.getSecurityManager()为空,所有操作可以正常进行
* ==========================
* 2 运行的配置安全管理器和安全策略文件,使用的是默认的安全管理器
* (PS:需要注意的是-Djava.security.policy,一个等号=代表同时也默认策略文件生效:java.policy
* 两个等号==代表只使用后面的策略文件,不是用默认的策略文件)
* VM options: -Djava.security.manager -Djava.security.policy="...\JavaExample\src\test\resources\conf\sjava.policy"
* 2.1 可以看到输出结果是必一样的,详情参考博客:
*/
public class TestMain {

public static void main(String[] args) {
// 获取系统的SecurityManager
System.out.println("系统当前的安全管理器:"+System.getSecurityManager());

String testFile = "C:\\Users\\Administrator\\Desktop\\fileTest.txt";
try {
FileInputStream fis = new FileInputStream(testFile);
} catch (Exception e) {
System.out.println(e.getMessage());
}

try{
// 正常读取(相关权限已经在java.policy中配置)
// -Djava.security.policy= 这样配置的时候不抛异常
// -Djava.security.policy==这样配置的时候会抛异常
System.out.println(System.getProperty("java.version"));
}catch (Exception e){
System.out.println(e.getMessage());
}

try{
// 读取异常(相关权限没有进行配置,需要在sjava.policy中配置)
System.out.println(System.getProperty("file.encoding"));
}catch (Exception e){
System.out.println(e.getMessage());
}
}
}

2.1、首先我们直接运行上面的实例,可以正常运行,输出内容如下:

系统当前的安全管理器:null
1.8.0_171
UTF-8

2.2 、配置默认的安全管理器以及自定义策略文件(默认策略文件也生效)之后再运行,配置和运行结果如下所示,从下面的运行结果可以看出,文件访问操作、file.encoding属性访问操作被限制,因为在sjava.policy和java.policy文件中都没有对这两个操作授权,当我们把sjava.policy中的权限放开,那么就不会出现该错误了:

配置:

sjava.policy配置

grant {
// 注解下面的权限配置会引起文件读取错误和配置信息读取错误
// permission java.util.PropertyPermission "file.encoding", "read";
// permission java.io.FilePermission "C:\\Users\\Administrator\\Desktop\\fileTest.txt", "read";
};

运行结果:

系统当前的安全管理器:java.lang.SecurityManager@77459877
access denied ("java.io.FilePermission" "C:\Users\Administrator\Desktop\fileTest.txt" "read")
1.8.0_171
access denied ("java.util.PropertyPermission" "file.encoding" "read")

2.2、配置默认权限管理器并启动程序(只使用指定的策略文件,默认的java.policy文件不生效),执行结果如下,可以从结果中看到读取java.version的操作被限制,该操作的权限的配置是默认在java.policy中的,当我们使用双等号“==”配置的时候,默认的java.policy配置不生效,那么该操作就会被禁止:

配置:

sjava.policy

grant {
// 注解下面的权限配置会引起文件读取错误和配置信息读取错误
permission java.util.PropertyPermission "file.encoding", "read";
permission java.io.FilePermission "C:\\Users\\Administrator\\Desktop\\fileTest.txt", "read";
};

执行结果:

系统当前的安全管理器:java.lang.SecurityManager@38af3868
access denied ("java.util.PropertyPermission" "java.version" "read")
UTF-8

 

总结

通过上面的实例的多种情况的运行调试分析,可以清晰的了解安全管理器的工作流程以及使实际使用的方法。在了解了java的安全管理机制之后,可以延伸到:加载执行远程下载的应用程序.......等,完整的实例的代码可以我已经放到我的github上了,感兴趣或者是想了解的可以clone出来调试分析,个人觉得应该还是会收获很多。


注意:本文归作者所有,未经作者允许,不得转载

全部评论: 0

    我有话说: