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

目录

  • 目录
  • 1 样例github
  • 2 安全管理器简介
    • 2.1 获取系统管理器
    • 2.2 设置系统管理器
    • 2.3 JDK默认安全策略文件
    • 2.4 自定义安全策略文件
  • 3 样例分析
    • 3.1 样例相关文件
    • 3.2 样例源码
  • 4 调试分析
    • 4.1 直接运行(无参数)
    • 4.2 配置默认安全管理器
    • 4.3 配置默认管理+自定义策略文件(=)
    • 4.4 配置默认管理+自定义策略文件(==)


1 样例github

https://github.com/mh47838704/JavaExample

参考文章:http://47777205.com/view/24


2 安全管理器简介

* 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安全管理器允许应用程序设置一个安全管理策略,通过安全管理策略实现对应用程序中的敏感的操作的管理(运行或者是禁制)

2.1 获取系统管理器

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

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

2.2 设置系统管理器

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


VM options: -Djava.security.manager

2.3 JDK默认安全策略文件

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

JDK\jre\lib\security\java.policy

2.4 自定义安全策略文件

问题又来了,当默认的策略不能满足我们的需求的时候怎么办呢?当然是自定义策略配置文件了,格式参考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";
};

3 样例分析

3.1 样例相关文件

本次测试中涉及到的代码和配置文件如下图所示:
JDK源码分析——SecurityManager安全管理器实例分析_第1张图片

其中java.policy是jdk默认的策略(只做参考,具体的路径参考前面的介绍),sjava.policy是自定义的安全策略文件,TestMain是测试代码文件

3.2 样例源码

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

4 调试分析

下面将通过几种运行方式来深入分析jdk的安全机制的运行原理:

运行条件 预估输出
(1)直接运行(不带任何vm_options参数) 正常运行,不会抛出任何异常
(2)配置默认安全管理器 抛出异常:1、文件读取异常;2、读取系统属性文件编码异常
(3)配置默认安全管理器;配置自定义安全策略(=:和默认安全策略文件同时生效) 正常运行
(4)配置默认安全管理器;配置自定义策略(==:默认安全策略文件不生效) 读取java.version异常

4.1 直接运行(无参数)

运行输出

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

4.2 配置默认安全管理器

运行输出

系统当前的安全管理器: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")

4.3 配置默认管理+自定义策略文件(=)

默认策略文件java.policy生效,正常输出:

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

4.4 配置默认管理+自定义策略文件(==)

运行输出:

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

你可能感兴趣的:(jdk,java)