Java SecurityManager解析

Java SecurityManager类解析

SecurityManager,顾名思义,安全管理,通俗地讲,该类用于对java程序的某些行为进行安全检查,判断该行为是否合法,是否要继续执行。

首先,我们来看看SecurityManager的构造方法:

    public SecurityManager() {
        synchronized(SecurityManager.class) {
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                // ask the currently installed security manager if we
                // can create a new one.
                sm.checkPermission(new RuntimePermission
                                   ("createSecurityManager"));
            }
            initialized = true;
        }
    }

我们在创建一个SecurityManager对象时,构造方法里会调用System类里的getSecurityManager()方法,System类下的getSecurityManager()与返回值security 成员变量如下:

private static volatile SecurityManager security = null;    
public static SecurityManager getSecurityManager() {
        return security;
    }

在没有对security赋值前,security为null,getSecurityManager()返回的也是null,在SecurityManager构造方法里,若System.getSecurityManager()返回是null,则不会执行if语句里的权限检查代码块。小伙伴们可能就想,System里既然有getSecurityManager(),那肯定也有相关的set方法,当然,不然的话一直返回null那不就没有意义了吗,我们来看看:

    public static
    void setSecurityManager(final SecurityManager s) {
        try {
            s.checkPackageAccess("java.lang");
        } catch (Exception e) {
            // no-op
        }
        setSecurityManager0(s);
    }

    private static synchronized
    void setSecurityManager0(final SecurityManager s) {
        SecurityManager sm = getSecurityManager();
        if (sm != null) {
            // ask the currently installed security manager if we
            // can replace it.
            sm.checkPermission(new RuntimePermission
                                     ("setSecurityManager"));
        }

        if ((s != null) && (s.getClass().getClassLoader() != null)) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                public Object run() {
                    s.getClass().getProtectionDomain().implies
                        (SecurityConstants.ALL_PERMISSION);
                    return null;
                }
            });
        }

        security = s;
    }

两个关于set的方法,我们来看最后一行代码 security = s; 这里就是开始设置System类里的security变量,设置后返回就不会是null了,而s由setSecurityManager0方法参数传进来,setSecurityManager0由setSecurityManager调用,我们最后回归到第一个set方法,第一个set方法的s变量也由外部传入。我想了想,System类或者其他类里在进行某些操作时会不会有自动调用setSecurityManager的方法,很抱歉没有,所以总结出来,该方法需要我们手动调用并赋值,大家就可以简单理解为:

我们需要手动开启SecurityManager的安全检查,开启后SecurityManager即可为其他方法行为进行权限检查

//示例Runtime里的exit方法进行时就会进行行为检查    
public void exit(int status) {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkExit(status);
        }
        Shutdown.exit(status);
    }

SecurityManager通过抛出异常来阻止没有权限或敏感操作的完成。 如果操作被允许执行,则简单的返回,如果操作被拒绝,则抛出一个SecurityException。 对于这种处理方式唯一的例外就是checkTopLevelWindow方法,此方法返回boolean值。

当前安全管理器被设置通过System类的setSecurityManager方法。获取当前安全管理器用System类的getSecurityManager方法。
SecurityManager中特定的方法checkPermission(java.security.Permission)负责明确允许还是拒绝由指定权限所指示的访问请求,默认的实现是:
AccessController.checkPermission(perm);
若果一个请求访问被允许,则checkPermission安静的返回,如果被拒绝,则抛出一个SecurityException异常。

从Java 2 SDK v1.2 开始,SecurityManager 中其他所有 check 方法的默认实现都是调用 SecurityManager checkPermission
方法来确定调用线程是否具有执行所请求操作的权限。

权限分为以下类别:文件、套接字、网络、安全性、运行时、属性、AWT、反射和可序列化。管理各种权限类别的类是   java.io.FilePermission

java.net.SocketPermission

java.net.NetPermission

java.security.SecurityPermission

java.lang.RuntimePermission

java.util.PropertyPermission

java.awt.AWTPermission

java.lang.reflect.ReflectPermission

java.io.SerializablePermission

   //示例,通过Runtime类的exit方法中的security.checkExit(status),我们来到SecurityManager类下的checkExit方法,该方法
   //就创建了RuntimePermission对象
   public void checkExit(int status) {
        checkPermission(new RuntimePermission("exitVM."+status));
    }

除前两个(FilePermission 和 SocketPermission)类以外的所有类都是 java.security.BasicPermission 的子类,而 java.security.BasicPermission 类又是顶级权限类 java.security.Permission 的抽象子类. BasicPermission 定义了所有权限所需的功能,这些功能的名称遵从分层属性命名惯例(例如“exitVM”、“setFactory”、“queuePrintJob”等等)。在名称的末尾可能出现一个星号,前面是“.”或星号,这表示通配符匹配。例如:“a.”、“”是有效的,而“a”或“ab”是无效的。
FilePermission 和 SocketPermission 是顶级权限类 (java.security.Permission) 的子类。像这些命名语法比 BasicPermission 所用的语法更为复杂的类都直接是 Permission 的子类,而不是 BasicPermission 的子类。例如,对于 java.io.FilePermission 对象而言,权限名就是文件(或目录)的路径名。

某些权限类具有一个“动作”列表,告知允许对象所执行的动作。例如,对于 java.io.FilePermission 对象,动作列表(如“读、写”)指定了允许对指定文件(或指定目录中的文件)执行哪些动作。其他权限类是“指定的”权限 - 有名称但没有动作列表的类;您也许有指定的权限,也许没有。注:还有一个暗指所有权限的 java.security.AllPermission 权限。该权限是为了简化系统管理员的工作而存在的,因为管理员可能需要执行很多需要所有(或许多)权限的任务。

SecurityManager应用场景:

当运行未知的Java程序的时候,该程序可能有恶意代码(删除系统文件、重启系统等),为了防止运行恶意代码对系统产生影响,需要对运行的代码的权限进行控制,这时候就要启用Java安全管理器。

启动安全管理器:

  • 参数启动(指定 -Djava.security.manager)
  • 通过程序打开SecurityManager SecurityManager sm = new SecurityManager(); System.setSecurityManager(sm);

关闭安全管理器:

程序关闭: SecurityManager sm = System.getSecurityManager(); if(sm != null){ System.setSecurityManager(null); }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值