https://github.com/mh47838704/JavaExample
参考文章:http://47777205.com/view/24
* 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安全管理器允许应用程序设置一个安全管理策略,通过安全管理策略实现对应用程序中的敏感的操作的管理(运行或者是禁制)
在Java中应用程序启动的时候是默认没有设置安全管理器的,可以通过下面的代码观察,下面的代码在常规的启动的时候会输出null:
System.out.println("系统当前的安全管理器:"+System.getSecurityManager());
在Java中可以通过配置启用jdk中默认的安全管理器,然后再使用上面的代码调试,那么会显示相应的实例,而不是null
VM options: -Djava.security.manager
在最前面说到了可以配置策略,那么策略到底是一个什么样的文件呢?既然在java中有默认的安全管理器,那么是不是也意味着有默认的策略配置文件呢?当然有,后面会对文件中的内容进行解释:
JDK\jre\lib\security\java.policy
问题又来了,当默认的策略不能满足我们的需求的时候怎么办呢?当然是自定义策略配置文件了,格式参考java.policy即可。那么如何使得我们的默认安全管理器加载呢?,使用如下启动命令参数即可(注意:一个等号“=”代表自定义策略文件和默认策略文件java.policy共同生效,两个等号“==”表示只有自定义策略文件生效)
VM options:-Djava.security.policy="...\JavaExample\src\test\resources\conf\sjava.policy"
自定义策略内容格式:
grant {
// 注解下面的权限配置会引起文件读取错误和配置信息读取错误
permission java.util.PropertyPermission "file.encoding", "read";
permission java.io.FilePermission "C:\\Users\\Administrator\\Desktop\\fileTest.txt", "read";
};
其中java.policy是jdk默认的策略(只做参考,具体的路径参考前面的介绍),sjava.policy是自定义的安全策略文件,TestMain是测试代码文件
TestMain.java
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());
}
}
}
下面将通过几种运行方式来深入分析jdk的安全机制的运行原理:
运行条件 | 预估输出 |
---|---|
(1)直接运行(不带任何vm_options参数) | 正常运行,不会抛出任何异常 |
(2)配置默认安全管理器 | 抛出异常:1、文件读取异常;2、读取系统属性文件编码异常 |
(3)配置默认安全管理器;配置自定义安全策略(=:和默认安全策略文件同时生效) | 正常运行 |
(4)配置默认安全管理器;配置自定义策略(==:默认安全策略文件不生效) | 读取java.version异常 |
运行输出
系统当前的安全管理器:null
1.8.0_171
UTF-8
运行输出
系统当前的安全管理器: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")
默认策略文件java.policy生效,正常输出:
系统当前的安全管理器:null
1.8.0_171
UTF-8
运行输出:
系统当前的安全管理器:java.lang.SecurityManager@38af3868
access denied ("java.util.PropertyPermission" "java.version" "read")
UTF-8