.Net運行時已經設計好了,一些懷有惡意的代碼不能滲透到遠程計算機上並 執行。目前一些分部式系統依懶於從遠程機器上下載和執行代碼。如果你可以通 過Internet或者以太網來發布你的軟件,或者直接從web上運行,但你須要明白 CRL在你的程序集中的一些限制。如果CLR不是完全相信一個程序集,它會限制一 些的行為。這些調用代碼要有訪問安全認證(CAS)。從另一方面來說,CLR強制要 求基於角色的安全認證,這樣這些代碼才能或者不能在基於一個特殊的角色帳號 下運行。
安全違例是運行時條件,編譯器不能強制它們。幸運的是,它 們絕不會在你的開發機器上出現,而且你所編譯的代碼從你自己的硬件上加載, 這就是說,它有更高的信任級別。討論所有潛在的.Net安全模型可以足足寫上幾 本書,但你可以了解合理行為的一小部份,這樣可以讓你的程序集與.Net的安全 模式更容易的交互。這些推薦只有在你創建一個組件程序庫時,或者是開發一些 通過網絡發布的組件和程序集是才可以參考應用。
通過這個討論,你應 該記住.Net是一個托管的環境。這個環境保證有一個明確的安全環境。在安裝時 可以用.Net的配置策略來管理安全策略。大多數.Net框架庫是在安裝時對配置策 略是安全信任的。它會查明安全問題,這就是說CLR可以檢測IL而且確保它不會 有什麼潛在的危險行為,例如直接訪問原始內存。它不會在訪問本地資源時要求 特殊的安全權限進行斷言。你應該試著遵守同樣的檢測,如果你的代碼不須要任 何的安全權限,就應該避免使用CAS的API來對斷定訪問權限,否則你所做的只是 降低程序性能。
你要使用CAS的API來訪問一些受保護的資源,而這些資 源是要求增加的特權的。很多通用的受保護資源是非托管的內存和文件系統。其 它一些受保護的資源還包括數據庫,網絡端口,windows注冊表,以及打印子系 統。在每種情況下,如果調用代碼沒有足夠的許可,試著訪問這些資源都會引發 一個異常。而且,訪問這些資源可能引發運行時建立一個安全棧上的詢訪,以確 保當前棧上的所有的程序集有恰當的許可。讓我們看一下內存以及文件系統,討 論安全系統和機密問題中最實際的一些問題。
不管什麼時候,你都可以 通過創建恰當的安全程序集來避免非托管內存訪問。一個安全的程序集,也就是 一個不用使用任何指針來訪問其它非托管,或者托管的堆內存。不管你是否知道 ,你所創建的所有C#代碼幾乎都是安全的。除非你在C#編譯器上打開了不安全的 編譯開關/unsafe,否則你所創建的都是安全代碼(譯注:就算打開了開關也不是 說就編譯成不安全代碼了,還要看你的代碼是怎樣寫的。)。/unsafe充許用戶使 用CLR不進行的驗證的指針。
要使用不安全代碼的原因很少,特別是一常 規的任務中。指向原始內存的指針比要檢測的安全的引用快一些。在一些經典的 數組中,它們可能要快上10倍以上。但當你使用不安全結構時,要明白任何的不 安全代碼都會影響整個程序集。當你創建不安全塊時,應該考慮把這些算法獨立 到一個程序信中(參見原則32)。這樣可以在整個程序上限制不安全代碼的影響。 如果它是獨立的,只有實際調用它的訪問者才會受到影響。其它剩下的,你還是 可以在更嚴格的環境中使用安全機制。你可能還須要不安全代碼來處理一些須要 直接指針的P/Invoke或者COM接口。同樣的推薦:獨立它。不安全代碼只會影響 它自己的小程序集,不再有其它的。
對於訪問的建議很簡單:只要可能 ,都應該避免訪問非托管內存。
接下來的安全核心就是文件系統。程序 要存儲數據。從Internet上下載回來的代碼,文件系統中的大多數地方都不能訪 問,否則會有很大的安全漏洞。是的,完全不許訪問文件系統就很難創建能使用 的程序。通過使用獨立存儲可以解決這一問題。獨立存儲可以穿越基於程序集而 獨立的虛擬的目錄,以及應用程序域,以及當前的用戶。選擇性的,你可以使用 更一般的獨立存儲虛擬目錄,該目錄是基於程序集或者當前用戶的。
實 際上,受信任的程序集可以訪問他們自己特殊的獨立存儲區域,但不能是文件系 統的其它地方。獨立的存儲目錄是隱藏在其它程序集以及其它用戶中的。你可以 使用System.IO.IsolatedStorage名字空間中的類來訪問獨立的存儲。 IsolatedStorageFile類包含的方法可以很簡單的訪問System.IO.File類。實際 上,它是從 System.IO. FileStream 類派生下來的。寫內容到獨立存儲的代碼 幾乎與寫內容到任何文件裡是一樣的:
IsolatedStorageFile iso =
IsolatedStorageFile.GetUserStoreForDomain( );
IsolatedStorageFileStream myStream = new
IsolatedStorageFileStream( "SavedStuff.txt",
FileMode.Create, iso );
StreamWriter wr = new StreamWriter( myStream );
// several wr.Write statements elided
wr.Close ();
讀操作也是完全和其它使用文件I/O相似的:
IsolatedStorageFile isoStore =
IsolatedStorageFile.GetUserStoreForDomain( );
string[] files = isoStore.GetFileNames( "SavedStuff.txt" );
if ( files.Length > 0 )
{
StreamReader reader = new StreamReader( new
IsolatedStorageFileStream( "SavedStuff.txt",
FileMode.Open,isoStore ) );
// Several reader.ReadLines( ) calls elided.
reader.Close ();
}
你可以獨立存儲來持久大小合適的數據元素,這些元 素可以被代碼部分信任,用於從一個安全分離的本地磁盤上的某個地方存儲和載 入信息。.Net環境為每個程序定義和限制了獨立存儲的大小。這可以預防一些惡 意的代碼占用磁盤空間,讓系統就得不可用。獨立存儲對於其它程序和其它用戶 來說是不可見的。也就是說,它不應用於要管理員手動操作才能布署或者配置設 置的情況。即使這它是隱藏的,然而,獨立存儲對於從受信任的用戶那來裡來的 非托管代碼來說也是不受保護的。不要用獨立存儲來存儲一些高度機密的內容, 除非你的程序給它加過密。
在文件系統中創建一個可能要許可安全策略 的程序集時,要獨立存儲流的內容。當你的程序集可能在web上運行,或者可能 被運行在web上的代碼訪問時,應該考慮使用獨立存儲。
你可能須要正確 的使用一個受保護的資源。一般情況下,訪問這些資源要指出你的程序要被完全 信任。唯一可選的就是完全避免使用這些受保護的資源。例如,考慮windows的 注冊表,如果你和程序須要訪問注冊表,你必須安裝你的程序到最終用戶的機器 上,這樣才能有必須的權限來訪問注冊表。你想簡單點,從web上運行的程序是 不能建立注冊表的修改的。安全策略就應該是這樣的。
.Net的安全模型 意味著你的程序的行為是要權得進行核對的。注意你的程序所要求的權利,而且 試著最小化它們。不必要求你不使用的權利。你的程序集越是少的要求受保護資 源,那麼它們就越是可以保證安全策略異常不拋出。避免使用機密資源,如果可 能,要考慮其它可選方案。當你在某個算法上確實須要更高安全的許可時,應該 獨立這些代碼到它們自己的程序集中。
返回教程目錄