AccessControlContext
类的调用过程上下文。它以栈的形式保存类的调用过程,如在上面例子中,ClassB 调用 ClassA,那么 AccessControlContext 的栈底是 ClassB,栈顶是 ClassA,如果 ClassA 再调用 ClassC,那么 ClassC 在压入栈,栈顶变成了 ClassC
ProtectionDomain
这是一个关键的类。它定义了“某些代码对某些资源具有某些操作权限”,亦即那个目录下的代码对那些资源有哪些操作权限。它有三个属性:
某些代码
一般是指某个目录下的所有代码,如 “JRE_HOEM/lib/ext”在 Java 中表示为 CodeBase
某些资源
比如 conf 目录下的文件,在 Java 中表现为某个文件(夹)路径 BasePath
某些权限
是指某些代码对对某些资源操作权限的集合,比如读权限、写权限,在 Java 中表现为 PermissionCollection 类。
PermissionCollection
权限的集合类。如文件读权限、文件写权限的集合:
FilePermission(file,SecurityConstants.FILE_WRITE_ACTION)
FilePermission(file,SecurityConstants.FILE_READ_ACTION)
Permission
某个具体的权限。如文件读权限 FilePermission(file,SecurityConstants.FILE_WRITE_ACTION)
Policy
“指定某些代码对某些资源具有某些操作权限”的策略定义在策略文件中,Policy 负责从配置文件中读取这些策略,并根据策略文件构建 ProtectionDomain。JVM 中只有一个 Policy 对象。
“某些代码对某些资源具有某些操作权限”建立过程
在 Java 中,每个类都有一个 ProtectionDomain 的一个引用,因为每个类都属于某个特定的目录下,这样就可以知道某个类对某些资源有哪些操作权限了。下面看每个类与 ProtectionDomain 建立关系的过程:
当 ClassLoader 去加载一个 class 的时候,它会把这个类及授给这个类的权限集封装到“java.security.ProtectionDomain”中,其中这些权限是通过 ClassLoader并根据策略文件进行分配的。
1) 找到类字节码的加载 URL
2) 如果这个类是从包 java.* 中加载的,那就把该类与内在的 System ProtectionDomain 关联,其中 System ProtectionDomain 是具有全部权限(AllPermission)的。如果该类不是从包 java.* 中加载的,则继续
3) 如果该类要关联的 ProtectionDomain 以及存在,则直接添加它们之间引用关系即可,否则继续
4) 创建一个 CodeSource 对象,里面封装了类字节码的加载路径
5) 创建一个 PermissionCollection 对象,并把策略文件中赋给 CodeSource 的权限封装到该 PC 对象中
6) 创建一个 ProtectionDomain,里面封装了 CodeSource 和 PermissionCollection 对象,即那些代码对那些资源有那些操作权限:ProtectionDomain = new ProtectionDomain(CodeSource,PermissionCollection)
7) 把刚加载的 class 类与当前的 ProtectionDomain 关联
各个类之间引用调用关系这里不阐述,下面继续看例子:
现在假设有如下代码:${user.dir}/testA/ClassA ${user.dir}/testB/ClassB
有如下资源:${user.dir}/conf/x.properties
加入在 Java 策略文件中添加如下策略:
grant codeBase "file:${user.dir}/testA/*" { permission java.io.FilePermission "${user.dir}/conf *", "read"; permission java.io.FilePermission "${user.dir}/conf *", "write"; }; grant codeBase "file:${user.dir}/testB/*" { permission java.io.FilePermission "${user.dir}/conf *", "read"; }; |