2. Java的安全模型

Java安全模型側重于保護終端用戶免受從網絡下載的、來自不可靠來源的、惡意程序(以及善意程序中的bug)的侵犯。為了達到這個目的,Java提供了一個用戶可配置的“沙箱”,在沙箱中可以放置不可靠的Java程序。

2.1 基本沙箱

沙箱模型使你可以接收來自任何來源的代碼,而不是要求用戶避免將來自不受信站點的代碼下載到機器上。

組成Java沙箱的基本組件如下:

  • 類裝載器結構
  • class文件檢驗器
  • 內置于Java虛擬機(及語言)的安全特性
  • 安全管理器及Java API

2.2 類裝載器體系結構

在Java沙箱中,類裝載器是第一道防線:

  • 它防止惡意代碼去干涉善意的代碼
  • 它守護了被信任的類庫的邊界
  • 它將代碼歸入某類(稱為保護域),該類確定了代碼可以進行哪些操作

類裝載器體系結構可以防止惡意的代碼去干涉善意的代碼,是通過為由不同的類裝載器裝入的類提供不同的命名空間來實現的。命名空間由一系列唯一的名稱組成,每一個被裝載的類有一個名字,這個命名空間是由Java虛擬機為每一個類裝載器維護的。

圖2-1 類裝載器和命名空間.png

類裝載器體系結構守護了被信任的類庫的邊界,是通過分別使用不同的類裝載器裝載可靠的包和不可靠的包來實現的。

從Java 1.2版本開始,類裝載器請求另一個用戶自定義類裝載器來裝載一個類型的過程被形式化,稱為雙親委派模式。除啟動類裝載器外的每一個類裝載器,都有一個“雙親”類裝載器,在某個特定的類裝載器試圖以常用方式裝載類型之前,它會先默認地將這個任務“委派”給它的雙親——請求它的雙親來裝載這個類型。

運行時包,是指由同一個類裝載器裝載的、屬于同一個包的、多個類型的集合。在允許兩個類型之間對包內可見的成員進行訪問前,虛擬機不但要確定這兩個類型屬于同一個包,還必須確認它們屬于同一個運行時包——它們必須是由同一個類裝載器裝載的。

除了屏蔽不同命名空間的類以及保護受信任的類庫的邊界外,類裝載器還起到了另外的安全作用。類裝載器必須將每一個被裝載的類放置在一個保護域中,一個保護域定義了這個代碼在運行時將得到怎樣的權限。

2.3 class文件檢驗器

和類裝載器一起,class文件檢驗器保證裝載的class文件內容有正確的內部結構,并且這些class文件相互間協調一致。如果class文件檢驗器在class文件中發現了問題,它會拋出異常。

JVM的class文件檢驗器只在字節碼執行之前進行一次分析,需要進行四趟獨立的掃描:

  • 第一趟是在類被裝載時進行的,主要檢查class文件的內部結構
  • 第二趟和第三趟是在連接過程中進行的,主要確認類型數據遵從Java編程語言的語義,包括檢驗它所包含的所有字節碼的完整性。
  • 第四趟是在動態連接的過程中解析符號時進行的,主要確認被引用的類、字段以及方法確實存在。

2.4 JVM中內置的安全特性

JVM在執行字節碼時還進行其他一些內置的安全機制的操作,包括:

  • 類型安全的引用轉換
  • 結構化的內存訪問(無指針算法)
  • 自動垃圾收集(不必顯式地釋放被分配的內存)
  • 數組邊界檢查
  • 空引用檢查

2.5 安全管理器和Java API

Java安全模型的前三個組成部分——類裝載器體系結構、class文件檢驗器以及Java中內置的安全特性——一起達到一個共同的目的:保持JVM的實例和它正在運行的應用程序的內部完整性,使得它們不被下載的惡意或有漏洞的代碼侵犯。相反,這個安全模型的第四個組成部分是安全管理器,它主要用于保護虛擬機的外部資源不被虛擬機內運行的惡意或有漏洞的代碼侵犯。

安全管理器定義了沙箱的外部邊界。因為它是可定制的,所以它允許為程序建立自定義的安全策略。

Java應用程序在啟動時不會默認安裝安全管理器,也不會有任何安全限制。在Java 1.2版本以前,如果安裝了安全管理器,那么它將負責應用程序整個剩余的生命周期,不能被替代、擴展或者修改。在1.2版本中,當前安裝的安全管理器能夠在允許的情況下被替換。

安全管理器主要負責兩個方面的工作:說明一個安全策略以及執行這個安全策略。

Java 1.2版本中的java.lang.SecurityManager是一個具體的類,它提供了一個默認的安全管理器的實現,能夠輔助建立一個基于代碼簽名的細粒度的安全策略。用戶可以顯示實例化這個安全管理器,或者讓它自動安裝。例如,在Sun的Java 2 SDK版本1.2中,可以在命令行使用-Djava.security.manager選項來指明安裝具體安全管理器。

具體安全管理器類允許用戶不用Java代碼定義自己的安全策略,而是用一個稱為策略文件的ASCII文件。在策略文件中,可以給代碼來源授予權限。權限是用類定義的,它是java.security.Permission的子類。代碼來源是由代碼庫的URL和一些簽名組成的,從這個URL可以裝載代碼,而簽名則為這個代碼作擔保。當創建安全管理器時,它對策略文件進行解析,并創建CodeSource(代碼來源)和Permission(權限)對象,這些對象被封裝在一個單獨的Policy對象中,這個Policy對象就代表了運行時的策略。任何時刻只能有一個Policy對象被安裝。

類裝載器將類型放到保護域(ProtectionDomain)中,保護域封裝了授予代碼來源的所有權限,這些代碼來源由裝載的類型代表。

當具體安全管理器的check方法被調用時,它們中的大多數都將請求傳遞給一個稱為AcessController的類。這個AccessController使用了包含在保護域對象中的信息,這個對象所屬的類的方法在調用棧中,AccessController進行棧檢查以確定這個操作能否被執行。

java.lang.SecurityManager中有兩個關鍵方法:

  • checkPermission(Permission perm) —— 進行某個操作(它需要指定的權限)前被調用
  • checkPermission(Permission perm, Object context) —— 在被傳遞的安全上下文中進行某個操作(它需要指定的權限)前被調用

在具體安全管理器類中,checkPermission( )方法同樣負責決定,是否允許將某個操作的任務委派給另一個方法。這個checkPermission( )方法只是簡單地調用了類java.security.AccessController中的靜態checkPermission( )方法,并將這個Permission對象傳遞給它。

2.6 代碼簽名和認證

Java安全模型很重要的一點就是它支持認證。認證可以使用戶確認,由某些團體擔保的一些class文件是值得信任的,并且這些class文件在到達用戶虛擬機的途中沒有被改變。這樣,如果用戶在一定程度上信任這個為代碼作擔保的團體,也就可以在一定程度上簡化沙箱對這段代碼的限制??梢詫τ刹煌瑘F體簽名的代碼建立不同的安全限制。

圖2-2 對一個jar文件簽名.png
圖2-3 對一個已簽名的jar文件驗簽.png

2.7 策略

Java安全體系結構的真正好處在于,它可以對代碼授予不同層次的信任度來部分地訪問系統。

版本1.2的安全體系結構的主要目標之一就是使建立(以代碼簽名為基礎的)細粒度的訪問控制策略的過程更為簡單且更少出錯。在版本1.2的安全模型中,權限(系統訪問權限)使授予代碼來源的。

對應于整個Java應用程序的一個訪問控制策略是由抽象類java.security.Policy的一個子類的單個實例所表示的。在任何時候,每個應用程序實際上都只有一個Policy對象。類裝在其利用這個Policy對象來幫助它們決定,在把一段代碼導入虛擬機時應該給它們怎么樣的權限。

安全策略是一個從描述運行代碼的屬性集合到這段代碼所擁有的權限的映射。在版本1.2的安全體系結構中,描述運行代碼的屬性被總稱為代碼來源。

在版本1.2中,所有和具體安全管理器有關的工具和訪問控制體系結構都只對證書起作用,而不能對“赤裸”的公鑰起作用。

權限是由抽象類java.security.Permission的一個子類的實例表示的。一個Permission對象有三個屬性:類型、名字和可選的操作。

在Policy對象中,每一個CodeSource是和一個或多個Permission對象相關聯的。

策略文件

由Sun提供的在Java 1.2平臺下的具體Policy子類采用如下方法:在一個ASCII策略文件中用上下文無關文法描述安全策略。

keystore "ijvmkeys";

grant signedBy "friend" {
    permission java.io.FilePermission "question.txt", "read";
    permission java.io.FilePermission "answer.txt", "read";
};

grant signedBy "stranger" {
    permission java.io.FilePermission "question.txt", "read";
};

grant codeBase "file:${com.artima.ijvm.cdrom.home}/security/ex2/*" {
    permission java.io.FilePermission "question.txt", "read";
    permission java.io.FilePermission "answer.txt", "read";
};

最后一條grant語句中的代碼庫URL采用了文件的形式:它包含了一個屬性${com.artima.ijvm.cdrom.home}。

2.8 保護域

當類裝載器將類型裝入JVM時,它們將為每個類型指派一個保護域。保護域定義了授予一段特定代碼的所有權限。(一個保護域對應于策略文件中的一個或多個grant子句。)裝載入JVM的每一個類型都屬于且僅屬于一個保護域。

雖然前面的Policy對象代表了一個從代碼來源到權限的全局映射,但是最終還是由類裝載器負責決定代碼執行時將獲得怎樣的權限。

圖2-4用圖形化的方式描述了保護域、代碼來源以及權限。ProtectionDomain對象封裝了一個到CodeSource對象的引用以及一個到java.security.Permissions對象的引用。java.security.Permissions是抽象類java.security.PermissionCollection的一個具體類,代表了一個同構權限的集合。

圖2-4 保護域、代碼來源以及權限.png

當一個類裝載器將Friend和Friend$1導入方法區時,類裝載器將把一個ProtectionDomain對象的引用和這些class文件的字節傳遞給defineClass( )方法。這個defineClass( )方法將Friend和Friend$1所在的方法區中的類型數據和被傳遞的ProtectionDomain對象相關聯。

2.9 訪問控制器

java.security.AccessController提供了一個默認的安全策略執行機制,它使用棧檢查來決定潛在不安全的操作是否被允許。

由AccessController的checkPermission( )實現的基本算法決定了調用棧中的每個幀是否有權執行潛在不安全的操作。每一個棧幀代表了由當前線程調用的某個方法,每一個方法是在某個類中定義的,每一個類又屬于某個保護域,每個保護域包含一些權限。因此,每個棧幀間接地和一些權限相關。

當調用doPrivileged( )方法時,就像調用其它任何方法一樣,都會將一個新的棧幀壓入棧。在由AccessController執行的棧檢查中,一個doPrivileged( )方法調用的棧幀標識了檢查過程的提前終止點。如果和調用doPrivileged( )的方法相關聯的保護域擁有執行被請求操作的權限,AccessController將立即返回。這樣這個操作就被允許,即使在棧下層的代碼可能沒有執行這個操作的權限。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,719評論 18 399
  • (一)Java部分 1、列舉出JAVA中6個比較常用的包【天威誠信面試題】 【參考答案】 java.lang;ja...
    獨云閱讀 7,129評論 0 62
  • 時差黨,美高生,坐標加州。 喜歡看書和寫作,酷愛風花雪月。 悲觀主義者,周期性焦慮。 對股市感興趣。未來打算去念經...
    眠舊時書閱讀 239評論 0 0
  • 寫不出東西的我 腦子一片混沌 像被關在一個封閉的大房子 四面的墻上涂滿了白漆 我盤坐在最中央 窒息感,孤獨感 充斥...
    做個作家夢閱讀 303評論 0 1
  • 2017年,對我而言,是一個悲喜交織的年份,悲的是,我的父親在今年夏天突然離世,我成了沒有雙親的人,父母在,人生尚...
    快樂英子閱讀 213評論 1 5