0 Java安全模型组成部分:
a) 类装载器 ---> 可以自定义
b) class文件校验器
c) 安全管理器 ---> 可以自定义
安全管理器作用: 对于外部资源的访问启动控制作用, 默认安全管理器是没有安装
通过代码简单看看安全管理器的作用:
protected ClassLoader(ClassLoader parent) { SecurityManager security = System.getSecurityManager();// 返回安全管理器对象java.lang.Security if (security != null) {//不为空时,安全管理器进行校验 security.checkCreateClassLoader(); } this.parent = parent; initialized = true; } // 进入 校验方法 public void checkCreateClassLoader() { checkPermission(SecurityConstants.CREATE_CLASSLOADER_PERMISSION); } // 进行进入后如下 public void checkPermission(Permission perm) { java.security.AccessController.checkPermission(perm); } // 继续进入如下 public static void checkPermission(Permission perm) throws AccessControlException { //System.err.println("checkPermission "+perm); //Thread.currentThread().dumpStack(); if (perm == null) { throw new NullPointerException("permission can't be null"); } AccessControlContext stack = getStackAccessControlContext(); // if context is null, we had privileged system code on the stack. 如果当前的访问控制器上下文为空,在栈上的系统代码将得到特权 if (stack == null) { Debug debug = AccessControlContext.getDebug(); boolean dumpDebug = false; if (debug != null) { dumpDebug = !Debug.isOn("codebase="); dumpDebug &= !Debug.isOn("permission=") || Debug.isOn("permission=" + perm.getClass().getCanonicalName()); } if (dumpDebug && Debug.isOn("stack")) { Thread.currentThread().dumpStack(); } if (dumpDebug && Debug.isOn("domain")) { debug.println("domain (context is null)"); } if (dumpDebug) { debug.println("access allowed "+perm); } return; } AccessControlContext acc = stack.optimize(); acc.checkPermission(perm); } 进入acc.checkPermission(perm);方法如下: 看注释即可, 大意是遍历上下文中的保护域,一旦发现请求的权限不被允许,停止,抛出异常 /* * iterate through the ProtectionDomains in the context. * Stop at the first one that doesn't allow the * requested permission (throwing an exception). * */ /* if ctxt is null, all we had on the stack were system domains, or the first domain was a Privileged system domain. This is to make the common case for system code very fast */ if (context == null) return; for (int i=0; i< context.length; i++) { if (context[i] != null && !context[i].implies(perm)) { if (dumpDebug) { debug.println("access denied " + perm); } if (Debug.isOn("failure") && debug != null) { // Want to make sure this is always displayed for failure, // but do not want to display again if already displayed // above. if (!dumpDebug) { debug.println("access denied " + perm); } Thread.currentThread().dumpStack(); final ProtectionDomain pd = context[i]; final Debug db = debug; AccessController.doPrivileged (new PrivilegedAction() { public Object run() { db.println("domain that failed "+pd); return null; } }); } throw new AccessControlException("access denied "+perm, perm); } }
通过上述代码一度跟踪流程,可知,安全管理器就是用来控制执行权限的。
默认下是没有开启的,通过如下代码来验证:
public class test2 { /** * @param args */ public static void main(String[] args) { System.out.println(System.getSecurityManager()); } }
结果为null,
重新换个方式运行,在ecplise里右键--Run As--Run Configuration--Arguments,在VM arguments的栏目里输入
-Djava.security.manager。在点击Run,结果为:
java.lang.SecurityManager@de6ced
这个时候默认的安全管理器就被安装上了。