认识java安全管理器SecurityManager

本文介绍了Java安全管理器的概念,其用于控制代码的权限,防止恶意代码破坏系统。讲解了启用安全管理器的两种方式,推荐使用启动参数方式,并解析了安全管理器配置文件的原则和实例。此外,还展示了代码中如何使用SecurityManager的checkXXX方法来检查权限。

1,什么是Java安全管理器?

SecurityManager
在看java源码的过程中,经常会遇到如下一段代码:

SecurityManager s = System.getSecurityManager();
ThreadGroup group = (s != null) ? 
s.getThreadGroup():Thread.currentThread().getThreadGroup()

SecurityManager security = System.getSecurityManager();
if (security != null) {
    security.checkWrite(name);
}

要想了解它们有什么功能,就需要对Java安全管理器有一定的认识。

2,Java安全管理器的使用场景?

当运行未知的java程序时,该程序可能含有恶意代码,如删除系统文件等恶意操作,为了防止恶意代码对系统的破坏,需要对运行代码的权限进行控制,这时候就需要启用java安全管理器。

3,如何启用java安全管理器?

方式1:启动参数方式 (推荐方式)

-Djava.security.manager

若同时需要指定安全管理器配置文件的位置使用如下参数,默认的配置文件按在**$JAVA_HOME/jre/lib/security/java.policy**

-Djava.security.manager -Djava.security.policy="E:/java.policy"

虽然通过启动参数指定,本质上也是通过代码方式启动,但是方式更灵活。原理可查看启动类 sun.misc.Launcher类,有如下一段代码

public Launcher() {
        Launcher.ExtClassLoader var1;
        try {
            var1 = Launcher.ExtClassLoader.getExtClassLoader();
        } catch (IOException var10) {
            throw new InternalError("Could not create extension class loader", var10);
        }

        try {
            this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
        } catch (IOException var9) {
            throw new InternalError("Could not create application class loader", var9);
        }

        Thread.currentThread().setContextClassLoader(this.loader);
        String var2 = System.getProperty("java.security.manager");
        if (var2 != null) {
            SecurityManager var3 = null;
            if (!"".equals(var2) && !"default".equals(var2)) {
                try {
                    var3 = (SecurityManager)this.loader.loadClass(var2).newInstance();
                } catch (IllegalAccessException var5) {
                } catch (InstantiationException var6) {
                } catch (ClassNotFoundException var7) {
                } catch (ClassCastException var8) {
                }
            } else {
                var3 = new SecurityManager();
            }

            if (var3 == null) {
                throw new InternalError("Could not create SecurityManager: " + var2);
            }

            System.setSecurityManager(var3);
        }

    }

方式2:编码方式启动(不推荐,不灵活)

System.setSecurityManager(new SecurityManager());

4,安全管理器配置文件解释

4.1 配置原则

  1. 没有配置的权限表示不具有权限
  2. 只能配置有什么权限,不能配置禁用什么权限
  3. 多种权限可用逗号分隔

4.2 配置文件解释

// 表示授权路径在 file:${{java.ext.dirs}}/* 
// 的所有jar和class 文件具有他们的权限
grant codeBase "file:${{java.ext.dirs}}/*" {
    permission java.security.AllPermission;
};
grant {
        // 如下都是一些细粒度的权限,可查资料了解,举几个例子
		// 授权  运行时权限   通过stop来停止线程
        permission java.lang.RuntimePermission "stopThread";
        // 授权  socket权限  监听权限
        permission java.net.SocketPermission "localhost:0", "listen";
        // 能读取java版本的权限
        permission java.util.PropertyPermission "java.version", "read";
        permission java.util.PropertyPermission "java.vendor", "read";
        permission java.util.PropertyPermission "java.vendor.url", "read";
        permission java.util.PropertyPermission "java.class.version", "read";
        permission java.util.PropertyPermission "os.name", "read";
        permission java.util.PropertyPermission "os.version", "read";
        permission java.util.PropertyPermission "os.arch", "read";
        permission java.util.PropertyPermission "file.separator", "read";
        permission java.util.PropertyPermission "path.separator", "read";
        permission java.util.PropertyPermission "line.separator", "read";

        permission java.util.PropertyPermission "java.specification.version", "read";
        permission java.util.PropertyPermission "java.specification.vendor", "read";
        permission java.util.PropertyPermission "java.specification.name", "read";

        permission java.util.PropertyPermission "java.vm.specification.version", "read";
        permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
        permission java.util.PropertyPermission "java.vm.specification.name", "read";
        permission java.util.PropertyPermission "java.vm.version", "read";
        permission java.util.PropertyPermission "java.vm.vendor", "read";
        permission java.util.PropertyPermission "java.vm.name", "read";
};

5,代码中使用java安全管理器场景

SecurityManager 实例包含了许多 checkXXX 的方法,表示检查是否具备对应的权限,如

sm.checkDelete("D:\\xx.txt");  // 是否具有指定文件的删除权限

当开启java安全管理器后,若没有对应的权限而执行了,就会抛出无权限的异常

Launcher failed - "Dump Threads" and "Exit" actions are unavailable (access denied ("java.io.FilePermission" "D:\install\IntelliJIDEA2020.1\bin\breakgen64.dll" "read"))
Exception in thread "main" java.security.AccessControlException: access denied ("java.io.FilePermission" "D:\xx.txt" "delete")
	at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
	at java.security.AccessController.checkPermission(AccessController.java:886)
	at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
	at java.lang.SecurityManager.checkDelete(SecurityManager.java:1007)
	at org.example.controller.SecurityManagerDemo.main(SecurityManagerDemo.java:8)

对于这类问题,我们只需要在安全管理器对应的配置文件中添加对应权限或者不启用安全管理器即可,如:

permission java.io.FilePermission "D:\\xx.txt","delete";

案例1:文件删除
查看 File 类的 delete 方法源码如下:

public boolean delete() {
  		SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkDelete(path);
        }
        if (isInvalid()) {
            return false;
        }
        return fs.delete(this);
    }

可以看出,在执行删除时,会用先获取安全管理器,然后调用checkDelete(path) 方法,检查是否具有该文件的删除权限。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值