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
这个时候默认的安全管理器就被安装上了。