当前位置:编程学习 > JAVA >>

java之jvm学习笔记(策略和保护域)

     前面一节,我们做了一个简单的实验,来说明什么是策略文件,在文章的最后,也顺带的讲了一下什么是策略,还有策略的作用。
                       为了引出另外一个很重要的概念ProtectionDomain(保护域),所以我们还是要先来回顾一下什么是策略。
                        首先,什么是策略,今天的东西纯粹是比较概念的。当然,如果你读过笔记九,今天的东西,就真的是soso
                       策略与策略文件:
                        java对应用程序的访问控制策略是由抽象类java.security.Policy的一个子类的单例所表示,任何时候,每个应用程序实际上只有一个Policy对象,Policy对象对应着策略文件。类装载器利用这个Policy对象来帮助他们决定,在把一段代码导入虚拟机时应该给予什么权限。
                        上面那段话告诉我们一个应用程序对应一个策略对象,一个策略对象对应一个策略文件。
                        那么策略文件,除了对我们笔记九中一个文件夹下的所有文件起限制作用外还能对什么主体起作用呢?先来看看下面的策略文件myPolicy.txt
keystore "ijvmkeys"

grant signedby "friend" {  
    permission java.io.FilePermission "d:/testPolicy.txt", "read,write";  
};

grant signedby "stranger" {  
    permission java.io.FilePermission "d:/testPolicy.txt", "read,write";  
};
 

grant codeBase "file:D:/workspace/TestPolicy/bin/*" {  
    permission java.io.FilePermission "d:/testPolicy.txt", "read,write";  
};
简单的解读一下
第一行:keystore "ijvmkeys",这一行的意思,密钥对存放在当前目录一个叫ijvmkeys的文件里(记得笔记八做过的jar包签名实验吗)
第二行:grant signedby "friend",grant是授权的意思,这一行的意思是,给一个被“friend”的密钥对签名的文件授权
第三行:permission java.io.FilePermission "d:/testPolicy.txt", "read,write";这行的意思是对于d:/testPolicy.txt赋予读写的权限
倒数第三行:grant codeBase "file:D:/workspace/TestPolicy/bin/*" 这一句我们笔记九的时候见过,就是对D:/workspace/TestPolicy/bin/*下的所有文件赋予权限。
重点一:到这里我们应该可以知道,策略文件可以给一系列被签名的代码库(“friend”,‘stranger“都是代码库)授权,也可以给一个代码来源(一个具体的路径或者说url就是一个代码来源)授权。
重点二:策略文件不仅可以存储在文件中(后缀名是什么不重要),还可以存放在数据库里。
              到了这里我们对策略有一个比较完整的概念了,但是你有没有这么一个疑问,前面我们总说,一个应用程序对应一个策略单例,一个策略单例对应一个策略文件,它到底怎么对应的?下面我们就来探究一下。
              在探究之前,我们先引入一个新的概念叫保护域(ProtectionDomain),在笔记三的时候,我们提到过类装载器将class文件load内存的时候会将它放置到一个保护域中,是滴今天我就来说说什么是保护域。
              什么是保护域
              当类装载器将类型装入Java虚拟机时,它们将为每个类型指派一个保护域。保护域定义了授予一段特定代码的所有权限。(一个保护域对应策略文件中的一个或多个Grant子句。)装载入Java虚拟机的每一个类型都属于一个且仅属于一个保护域。
              类装载器知道它装载的所有类或接口的代码库和签名者。它利用这些信息来创建一个CodeSource对象。它将这个CodeSource对象传递个当前Policy对象的getPermissions()方法,得到这个抽象类java.security.PermissionCollection的子类实例。这个PermissinCollection包含了到所有Permission对象的引用(这些Permission对象由当前策略授予指定代码来源)。利用它创建的CodeSource和它冲Policy对象得到的PermissionCollection,它可以实例化一个新的ProtectDomain对象。它通过将合适的ProtectionDomain对象传递给defineClass()方法,来将这段代码放到一个保护域中
                                 如果你对上面这段话理解不了,看下面这个图

   好了看完上面的这整个过程之后你是否已经理解什么是保护域了。
下面我们在整理一下内容,概念有点多,一个一个的来。
codeSource:代码源,这个是类装载器生成的java.security.CodeSource的一个对象,classLoader通过读取class文件,jar包得知谁为这个类签过名(可以有过个签名者,关于签名请查看笔记七和八)而封装成一个签名者数组赋给codeSource对象的signers成员,通过这个类的来源(可能来自一个本地的url或者一个网络的ur,对应了grant笔记九里myPollicy里的"friend"或者file::....l)赋给codeSource的location成员,还有这个类的公钥证书赋给codeSource的certs成员(通常一个jar是能够被多个团体或者机构担保的,也就是我们说的认证,在java1.2的默认安全管理器还有访问控制体系结构都只能对证书起作用,而不能对赤裸的公钥起作用,而实际上,我们用keytool生成密钥对时,同时会生成一个自签名证书,所以keytool生成的密钥对并不是赤裸的)。如果你有疑问,我们看一下jdk里的代码
public class CodeSource implements java.io.Serializable {

    private static final long serialVersionUID = 4977541819976013951L;

    /**
     * The code location.
     *
     * @serial
     */
    private URL location;//本地代码库
    /*
     * The code signers.
     */
    private transient CodeSigner[] signers = null;//签名者

    /*
     * The code signers. Certificate chains are concatenated.
     */
    private transient java.security.cert.Certificate certs[] = null;//证书

Policy:策略,就是用来读取策略文件的一个单例对象,通过传入的CodeSource对象(由于codeSource对象里包含了签名者和代码来源)所以他通过读取grant段,取出一个个的Perssiom然后返回一个PerssiomCollection。这个类里有一个很重要的成员变量
    // Cache mapping  ProtectionDomain to PermissionCollection
    private WeakHashMap pdMapping;

这个成员为什么重要,我们来看一个方法
    private static void initPolicy (final Policy p) {
              ......
 
      if (policyDomain.getCodeSource() != null) {
       .......
     synchronized (p.pdMapping) {
  // cache of pd to permissions
  p.pdMapping.put(policyDomain, policyPerms);
     }
 }
 return;
    }

我们主要看关键代码。这个pdMapping就是把保护域对象当做key将权限集合当做value存在在了这个map里。所以我们说一个保护域对应多个策略文件的grant子句的permission。
ProtectionDomain:保护域,前面我们已经介绍过了,他就是用来容纳class文件,还有perssiom,codeSource的

补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,