2025-02-09

程序員寫一個Java程序,默認的情況下你可以訪問任意的機器資源,比如讀取,刪除一些文件或者網絡操作等。當你把程序部署到正式的服務器上,系統管理員要為服務器的安全承擔責任,那麼他可能不敢確定你的程序會不會訪問不該訪問的資源,為瞭消除潛在的安全隱患,他可能有兩種辦法:1,讓你的程序在一個限定權限的帳號下運行;
2.利用Java的沙箱機制來限定你的程序不能為非作歹。我們這裡主要談談後一種方法。


怎樣給一個程序設置一個“沙箱”呢?這個設置應該是避免改動程序代碼的,而且是簡單易行的。根據Java的文檔,我們瞭解到隻需簡單的兩個步驟。


步驟一.加一個運行參數,就可以讓一個程序在沙箱裡運行:
   java -Djava.security.manager -jar myapp.jar


步驟二.設置具體的權限,比如創建自己的策略文件myapp.policy:
   grant codeBase “file:${user.dir}/myapp.jar” {


    permission java.io.FilePermission “${user.dir}${/}*”, “read”;


   };


這個設置的意思是,從myapp.jar載入的代碼,對當前目錄下的所有文件有“讀”的權限。


做完這兩個步驟後,運行命令:
   java -Djava.security.manager -Djava.security.policy==myapp.policy -jar myapp.jar


就可以保證程序隻擁有你指明的權限。當訪問其他資源時,會拋出類似”access denied”的異常。系統默認的策略文件是${java.home}/jre/lib/security/java.policy,它擁有的權限非常少,而且都與訪問系統資源無關。


那麼問題隨之而來,這一切是怎麼實現的?檢查的代碼在哪裡,又是誰來開發的這些代碼?


答案是:這是SUN幹的,SUN早把這些檢查的代碼插入到所有訪問系統資源的API裡面瞭。


舉一個讀取文件的例子,比如:
     BufferedReader br = new BufferedReader(new FileReader(fileName));
     String line = br.readLine();


當你運行到第一行,繼續調試進Java API源代碼裡,就可以碰到下面的一段代碼:


SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkRead(name);
    }


這裡的代碼表示,如果安裝瞭SecurityManager,那麼將進行安全檢查(是否對這個文件具有讀的權限)。而當你加上運行參數-Djava.security.manager,即表示安裝瞭SecurityManager。這裡和上面的第一個步驟對應。


繼續調試進去,看到下面的代碼:
checkPermission(new FilePermission(file,
        SecurityConstants.FILE_READ_ACTION));


很明顯,這和上面的第二個步驟對應,FilePermission即為java.io.FilePermission,FILE_READ_ACTION即為“read”。
那麼codeBase和什麼對應呢?


codeBase涉及到ClassLoader方面的知識瞭,簡單的說,ClassLoader加載一些代碼的時候,它會把代碼來源的信息保存下來,這些信息結合從策略文件裡讀取的信息,系統就可以來做出決策瞭。


細節總是復雜的,但在理解這個原理後去深入細節,就能起到引領的作用。 這裡最讓人疑惑的地方不是策略文件的配置和規則,而是誰在決策,在什麼時候決策。可能有人提出一個問題,如果我不用SUN的API,我自己去寫一些代碼訪問機器上的資源,那不就可以繞開“沙箱”瞭嗎?理論上是可以的,但隻要你寫的是Java代碼,並且仍使用SUN的虛擬機,那麼你就沒有這個機會。SUN的類加載器機制保證瞭你不能去替代或者幹涉它的核心類庫。


本文來自CSDN博客,轉載請標明出處:aspx”>http://blog.csdn.net/kevinkevin/archive/2010/12/04/6054980.aspx

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *