zoukankan      html  css  js  c++  java
  • java之jvm学习笔记四(安全管理器)

     java之jvm学习笔记四(安全管理器)

                   前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器。

                   安全管理器是一个单独的对象,在java虚拟机中,它在访问控制-对于外部资源的访问控制-起到中枢作用

                    如果光看概念可能并不能很好的理解,或者说比较抽象,下面是ClassLoader其中的一个构造函数,先简单的看看它在初始化ClassLoader之前会做一些什么操作

                   

    1. protected ClassLoader(ClassLoader parent) {  
    2.     SecurityManager security = System.getSecurityManager();  
    3.     if (security != null) {  
    4.         security.checkCreateClassLoader();  
    5.     }  
    6.     this.parent = parent;  
    7.     initialized = true;  
    8.     }  



    这个构造函数的第一话(当然还有隐式调用)就是System.getSecurityManager();这行代码返回的就是一个安全管理器对象security,这个对象所属的目录为java.lang.SecurityManager。

    这个构造函数先判断如果已经安装了安全管理器security(在前面类装载器的章节,我们提到过,类装载器和安全管理器是可以由用户定制的, 在这里有了体现吧!!既然有System.getSecurityManager();你当然也应该猜到有 System.setSecurityManager();),也就是安全管理器不为空,那么就执行校验,跳到 checkCreateClassLoader();看看他做的是什么操作

    1. public void checkCreateClassLoader() {  
    2. heckPermission(SecurityConstants.CREATE_CLASSLOADER_PERMISSION);  
    3.   }  

     


    这里又调用了另外一个方法,从方法名字上,就可以猜到这个方法是用来校验权限的,校验是否有创建ClassLoader的权限,再跳到checkPermisson方法里

     

    1.    public static void checkPermission(Permission perm)  
    2.    throws AccessControlException   
    3.     {  
    4.  //System.err.println("checkPermission "+perm);  
    5.  //Thread.currentThread().dumpStack(); if (perm == null) {  
    6.      throw new NullPointerException("permission can't be null");  
    7.  } AccessControlContext stack = getStackAccessControlContext();  
    8.  // if context is null, we had privileged system code on the stack.  
    9.  if (stack == null) {  
    10.      Debug debug = AccessControlContext.getDebug();  
    11.      boolean dumpDebug = false;  
    12.      if (debug != null) {  
    13.   dumpDebug = !Debug.isOn("codebase=");  
    14.   dumpDebug &= !Debug.isOn("permission=") ||  
    15.       Debug.isOn("permission=" + perm.getClass().getCanonicalName());  
    16.      }     if (dumpDebug && Debug.isOn("stack")) {  
    17.   Thread.currentThread().dumpStack();  
    18.      }     if (dumpDebug && Debug.isOn("domain")) {  
    19.   debug.println("domain (context is null)");  
    20.      }     if (dumpDebug) {  
    21.   debug.println("access allowed "+perm);  
    22.      }  
    23.      return;  
    24.  } AccessControlContext acc = stack.optimize();  
    25.  acc.checkPermission(perm);  
    26.     }  
    27. }  


     


     

    上面的这个方法有些代码比较难以理解,我们不用每行都读懂(这个方法涉及的东西比较多,它涉及到了代码签名认证,策略还有保护域,这些我们在后一节中会详细的讲解,看不懂先跳过), 看它的注解// if context is null, we had privileged system code on the stack.意思就是如果当前的访问控制器上下文为空,在栈上的系统代码将得到特权,找到acc.checkPermission(perm);再跳进去 找到下面这段代码

     

    1. /* 
    2.   * iterate through the ProtectionDomains in the context. 
    3.   * Stop at the first one that doesn't allow the 
    4.   * requested permission (throwing an exception). 
    5.   * 
    6.   */ /* if ctxt is null, all we had on the stack were system domains, 
    7.     or the first domain was a Privileged system domain. This 
    8.     is to make the common case for system code very fast */ if (context == null)  
    9.      return; for (int i=0; i< context.length; i++) {  
    10.      if (context[i] != null &&  !context[i].implies(perm)) {  
    11.   if (dumpDebug) {  
    12.       debug.println("access denied " + perm);  
    13.   }  if (Debug.isOn("failure") && debug != null) {  
    14.       // Want to make sure this is always displayed for failure,  
    15.       // but do not want to display again if already displayed  
    16.       // above.  
    17.       if (!dumpDebug) {  
    18.    debug.println("access denied " + perm);  
    19.       }  
    20.       Thread.currentThread().dumpStack();  
    21.       final ProtectionDomain pd = context[i];  
    22.       final Debug db = debug;  
    23.       AccessController.doPrivileged (new PrivilegedAction() {  
    24.    public Object run() {  
    25.        db.println("domain that failed "+pd);  
    26.        return null;  
    27.    }  
    28.       });  
    29.   }  
    30.   throw new AccessControlException("access denied "+perm, perm);  
    31.      }  
    32.  }  


     


     

    什么都不用看,就看最上面的那段注解,意思是遍历上下文中的保护域,一旦发现请求的权限不被允许,停止,抛出异常,到这里我们有一个比较清晰的概念了,安全管理器就是用来控制执行权限的,而上面的这段代码中有一个很重要的类 AccessController,访问控制器,还有一个很重要的名词保护域(保护域我们在前面一节也有简单的带过一下,是不是有点印象),这些可能现在听有点模糊,不要担心,暂时不要管,后面一章节慢慢的会对他们进行讲解。


    好了了解安全管理器是做什么的之后,接下来,来做一个下的实验,先来验证,默认安全管理是没 有被安装的,接着来试着把他安装上去。在我的环境中我是没有安装默认的安全管理器的,也没有基于默认的安全管理器写自己的安全管理器,如果需要打开的话, 可以在程序显示的安装安全管理器,同样可以让它自动安装默认的安全管理器(给jvm加上-Djava.security.manager就可以了。

    下面我们用熟悉的ecplise写一个简单的demo来看看安装前后的区别,在下一节中,会详细的来学习代码签名认证和策略,并写一个自己的安全管理器。

    1. <span style="font-size:14px;">  public static void main(String[] args) {  
    2.         System.out.println(System.getSecurityManager());  
    3.     }</span>  

    运行这个main函数,输出什么?是的输出null,这个时候我们没有安装默认的安全管理器

    重新换个方式运行,在ecplise里右键--Run As--Run Configuration--Arguments,在VM arguments的栏目里输入

    -Djava.security.manager。在点击Run,这个时候看到什么?

    输出:securityManager的对象名。这个时候默认的安全管理器就被安装上了。

     

    总结:

          在java虚拟机中,它在访问控制-对于外部资源的访问控制-起到中枢作用

     

  • 相关阅读:
    基于Python自动生成小学四则运算题目的命令行程序(软工第二次作业)
    第一次个人编程作业
    自我介绍+软工五问
    如何清理 Docker 占用的磁盘空间
    复审与事后分析
    团队作业5——测试与发布(Alpha版本)
    项目冲刺总结集合贴
    团队作业3:需求改进&系统设计
    团队作业2——需求规格说明书
    团队作业1——团队展示&选题
  • 原文地址:https://www.cnblogs.com/timssd/p/4790478.html
Copyright © 2011-2022 走看看