java之jvm學習筆記四(安全管理器)


               歡迎裝載請說明出處:http://blog.csdn.net/yfqnihao

               前面已經簡述了java的安全模型的兩個組成部分(類裝載器,class文件校驗器),接下來學習的是java安全模型的另外一個重要組成部分安全管理器。

               安全管理器是一個單獨的對象,在java虛擬機中,它在訪問控制-對於外部資源的訪問控制-起到中樞作用

                如果光看概念可能並不能很好的理解,或者說比較抽象,下面是ClassLoader其中的一個構造函數,先簡單的看看它在初始化ClassLoader之前會做一些什么操作

               

protected ClassLoader(ClassLoader parent) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkCreateClassLoader();
}
this.parent = parent;
initialized = true;
}



這個構造函數的第一話(當然還有隱式調用)就是System.getSecurityManager();這行代碼返回的就是一個安全管理器對象security,這個對象所屬的目錄為java.lang.SecurityManager。

這個構造函數先判斷如果已經安裝了安全管理器security(在前面類裝載器的章節,我們提到過,類裝載器和安全管理器是可以由用戶定制的,在這里有了體現吧!!既然有System.getSecurityManager();你當然也應該猜到有System.setSecurityManager();),也就是安全管理器不為空,那么就執行校驗,跳到checkCreateClassLoader();看看他做的是什么操作

  public void checkCreateClassLoader() {
checkPermission(SecurityConstants.CREATE_CLASSLOADER_PERMISSION);
}

 


這里又調用了另外一個方法,從方法名字上,就可以猜到這個方法是用來校驗權限的,校驗是否有創建ClassLoader的權限,再跳到checkPermisson方法里

 

   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);
}
}


 


 

上面的這個方法有些代碼比較難以理解,我們不用每行都讀懂(這個方法涉及的東西比較多,它涉及到了代碼簽名認證,策略還有保護域,這些我們在后一節中會詳細的講解,看不懂先跳過),看它的注解// if context is null, we had privileged system code on the stack.意思就是如果當前的訪問控制器上下文為空,在棧上的系統代碼將得到特權,找到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);
}
}


 


 

什么都不用看,就看最上面的那段注解,意思是遍歷上下文中的保護域,一旦發現請求的權限不被允許,停止,拋出異常,到這里我們有一個比較清晰的概念了,安全管理器就是用來控制執行權限的,而上面的這段代碼中有一個很重要的類 AccessController訪問控制器,還有一個很重要的名詞保護域(保護域我們在前面一節也有簡單的帶過一下,是不是有點印象),這些可能現在聽有點模糊,不要擔心,暫時不要管,后面一章節慢慢的會對他們進行講解。


好了了解安全管理器是做什么的之后,接下來,來做一個下的實驗,先來驗證,默認安全管理是沒有被安裝的,接着來試着把他安裝上去。在我的環境中我是沒有安裝默認的安全管理器的,也沒有基於默認的安全管理器寫自己的安全管理器,如果需要打開的話,可以在程序顯示的安裝安全管理器,同樣可以讓它自動安裝默認的安全管理器(給jvm加上-Djava.security.manager就可以了。

下面我們用熟悉的ecplise寫一個簡單的demo來看看安裝前后的區別,在下一節中,會詳細的來學習代碼簽名認證和策略,並寫一個自己的安全管理器。

public static void main(String[] args) {
System.out.println(System.getSecurityManager());
}

運行這個main函數,輸出什么?是的輸出null,這個時候我們沒有安裝默認的安全管理器

重新換個方式運行,在ecplise里右鍵--Run As--Run Configuration--Arguments,在VM arguments的欄目里輸入

-Djava.security.manager。在點擊Run,這個時候看到什么?

輸出:securityManager的對象名。這個時候默認的安全管理器就被安裝上了。

 

總結:

      在java虛擬機中,它在訪問控制-對於外部資源的訪問控制-起到中樞作用

 

writed by:keycoding


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com