JAVA的安全模型不同於傳統的安全方法
傳統的安全方法中
大多數操作系統允許應用程序充分訪問系統資源
在操作系統不提供安全保護的機器裡
運行環境不能被信任
為了彌補這個缺陷
安全策略經常要求在應用程序執行之前對應用程序建立信任
例如要求程序員在執行從網上獲得的應用程序前
先檢查病毒和源代碼中不安全的代碼
這種方法有
個問題
(
)確定程序是否安全的檢查很復雜很浪費時間
很少有程序員願意花時間讀程序的源代碼
然後再將它編譯成本地機器碼以保證程序是安全的
(
)病毒檢查要不斷維護以保證有效性
JAVA的安全模型是不同的
為了防止用戶系統受到通過網絡下載的不安全程序的破壞
JAVA提供了
個自定義的可以在裡面運行JAVA程序的
沙盒
JAVA的安全模型使得JAVA成為適合於網絡環境的技術
JAVA的安全性允許用戶從Internet或Intranet上引入或運行applet
applet的行動被限制於它的
沙盒
applet可以在沙盒裡做任何事情
但不能讀或修改沙盒外的任何數據
沙盒可以禁止不安全程序的很多活動
如
對硬盤進行讀寫
和別的主機(不包括程序所在的主機)進行網絡連接
創建
個新過程
載入
個新的動態庫並直接調用本地方法
沙盒
模型的思想是在信任的環境中運行不信任的代碼
這樣即使用戶不小心引入了不安全的applet
applet也不會對系統造成破壞
沙盒
模型
沙盒
安全模型是內建於JAVA結構的
它主要由以下幾部分構成
內建於JAVA虛擬機和語言的安全特性
類的載入結構
類文件校驗器
安全管理器和JAVA API
下面分別進行闡述
內建於JAVA虛擬機和語言的安全特性
JAVA語言有一些機制使得JAVA程序很穩健
這些機制也是JAVA虛擬機(JVM)的特點
它們是
安全的類型轉換
在C
C++中
可以通過指針進行任意的類型轉換
但常常帶來不安全性
而在JAVA中
運行時系統對對象的處理要進行類型相容性檢查
以防止不安全的轉換
沒有指針
指針是C和C++中最靈活
也最容易產生錯誤的數據類型
由指針所進行的內存地址操作常會造成不可預知的錯誤
同時通過指針對某個內存地址進行顯示類型轉換後
可以訪問
個C++中的私有成員
從而破壞安全性
造成系統的崩潰
而JAVA對指針進行完全的控制
程序員不能直接進行任何指針操作
自動的垃圾收集
在C中
程序員通過庫函數malloc()和free()來分配和釋放內存
C++中則通過運算符new和delete來分配和釋放內存
再次釋放已釋放的內存塊或未被分配的內存塊
會造成系統的崩潰
同樣
忘記釋放不再使用的內存塊也會逐漸耗盡系統資源
而在JAVA中
所有的數據結構都是對象
通過運算符new為它們分配內存堆
通過new得到對象的處理權
而實際分配給對象的內存可能隨程序運行而改變
JAVA對此自動進行管理並且進行垃圾收集
有效地防止了由於程序員的誤操作而導致的錯誤
並且更好地利用了系統資源
數組界限檢查
若程序中有數組訪問
JVM就會檢查數組訪問是否越界
從而防止了由數組越界引起的錯誤
檢查null引用
若使用的引用為null
JVM就會拋出
個例外
類載入器結構
類載入器結構在沙盒模型中起了重要作用
在虛擬機中
類載入器負責引入
定義運行程序的類和接口的二進制數據
在虛擬機中可能有不止
個類載入器
個JAVA程序能使用
種類型的類載入器
原始的類載入器和類載入器對象
原始的類載入器是JVM實現的
部分
它通常從本地硬盤載入安全的類
包括JAVA API的類
運行時
JAVA應用程序安裝類載入器對象
類載入器對象使用JAVA語言編寫
編譯成類文件後
載入到虛擬機
像其他的對象一樣初始化
類載入器對象用於以自定義的方式載入類
例如通過網絡下載類文件
JVM把通過原始的類載入器載入的任何類都視為安全的
無論這個類是否是JAVA API的
部分
而將通過類載入器對象載入的類視為可懷疑的
缺省情況下視為不安全的
JAVA的結構可以在
個應用程序中創建多個命名空間
命名空間是由
個特定的類載入器載入的類名的集合
JVM為每
個類載入器維持
個命名空間
這個命名空間裡有由那個類載入器載入的所有類的名字
由不同類載入器載入的類在不同的命名空間裡
沒有程序的直接允許
這些類不能彼此訪問
編寫程序時
可以將來源不同的類放在不同的命名空間裡
用這種方式
就可以使用JAVA的類載入器結構控制來源不同的代碼間的相互作用
就可以防止不安全代碼訪問
破壞安全代碼
對於Applet
也是同樣的道理
通過將來源不同的Applet類文件放在不同的命名空間
防止不安全代碼破壞安全代碼
在
沙盒
結構中
類載入器結構是防止不安全代碼的第一道圍牆
它的作用主要有
方面
防止不安全代碼訪問
破壞安全代碼
防止不安全代碼冒充安全的類
這
方面作用是通過下述方法實現的
將代碼分放在多個命名空間中
並在不同命名空間的代碼之間設置
屏障
類載入器結構是通過命名空間來防止不安全代碼訪問
破壞安全代碼
命名空間在載入到不同命名空間中的類之間設置了
個
屏障
在JVM中
同一命名空間中的類可以直接相互作用
不同命名空間中的類甚至不能檢測到對方的存在
除非程序允許它們相互作用
保護可信任類庫(像JAVA API)的邊界
如果類載入器載入
個類
這個類用它的名字來冒充是JAVA API的
部分(例如
類名為java
lang
virus)
類載入器就傳遞請求給原始類載入器
如果原始類載入器不能載入這個類
類載入器就拋出安全例外
並拒絕載入這個類
類文件校驗器
每一個JVM都有
個類文件校驗器
用來保證載入的類文件具有正確的內部結構
如果類文件校驗器發現類文件有錯誤
它就拋出
個例外
類文件校驗器能幫助檢查出類使用起來是否安全
因為類文件是由二進制數據構成的
JVM不知道這個類文件是否是由黑客產生的
是否有可能破壞虛擬機的完整性
所以虛擬機對引入的字節碼進行校驗是很重要的
類文件校驗器校驗的過程可以分為
個階段
階段
發生在類剛載入以後
類文件校驗器檢查類文件的內部結構
包括校驗所含的字節碼的完整性
階段
發生在字節碼執行的時候
字節碼校驗器確定符號引用的類
域和方法是否存在
內部檢查
在階段
類文件校驗器檢查類文件是否正確組成
內部是否一致
是否遵循JAVA編程語言的限制
含有的字節碼是否能由JVM安全執行
如果類文件校驗器檢查出錯誤
它就會拋出
個錯誤
類文件就不再被程序使用
檢查格式和內部一致性
在階段
校驗器除了檢查字節碼的完整性
還要檢查類文件的格式和內部一致性
例如
每一個類文件都必須以同樣的
字節數字
xCAFEBASE開頭
這樣類文件校驗器可能檢查的第一件事就是引入的文件是否以
xCAFEBASE開頭
類文件校驗器還要校驗類文件的長度是否與類文件中所記錄的長度一致
也即校驗類文件是否完整
是否被截去一部分或者被添加
類文件校驗器還要檢查類是否遵循Java語言的規定
如除了Object類
所有的類都必須有
個父類等
字節碼校驗
一旦類文件校驗器成功地完成格式和內部一致性的檢查
就開始對字節碼進行校驗
通過對代表類方法的字節碼流進行數據流分析
進行操作碼是否有效及操作碼是否有有效的操作數等的檢查
以驗證字節碼流是否可以由虛擬機安全執行
符號引用的校驗
符號引用是給出了引用項的名字和其它信息的字符串
這些信息足以用來區分類
域或方法
符號引用的校驗用來驗證引用是否有效
如果引用無效(例如
如果類不能載入
或者類存在但不含有要引用的域或方法)
類文件校驗器就會拋出
個錯誤
安全管理器和JAVA API
安全管理器定義了
沙盒
的外部邊界
安全管理器是類java
lang
SecurityManager的子類
它是自定義的
JAVA API類在采取一些行動時
通常需要安全管理器檢查這個行動是否安全
這些行動包括
接受來自於特定主機的socket連接
修改線程(改變線程優先級
結束線程等)
開放對於特定主機的socket連接
創建
個新的類載入器
刪除特定的文件
創建新的過程
程序退出
調用含有本地方法的動態庫
等待連接
從特定的包載入類
給特定的包中添加
個新類
訪問或修改系統特性
訪問特定的系統特性
讀文件
寫文件
由於在執行上述動作前需要安全管理器進行檢查
JAVA API不執行安全管理器建立的安全措施所禁止的任何動作
JAVA API執行
個可能不安全活動的過程
通常分為
步
首先
JAVA API代碼檢查安全管理器是否已安裝
如果沒有安裝
就無法進行第
步的檢查
則直接執行可能不安全的代碼
如果安裝了
就繼續執行第
步的檢查
調用安全管理器中合適的檢查方法對動作進行檢查
如果動作被禁止
檢查方法就
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27554.html