網絡技術是從1990年代中期發展起來的新技術,它把互聯網上分散的資源融為有機整體,實現資源的全面共享和有機協作,使人們能夠透明地使用資源的整體能力并按需獲取信息。資源包括高性能計算機、存儲資源、數據資源、信息資源、知識資源、專家資源、大型數據庫、網絡、傳感器等。 當前的互聯網只限于信息共享,網絡則被認為是互聯網發展的第三階段。 前面介紹堆棧幀時曾經提到過,對所有跨越 Assembly/AppDomain 的調用,都會有特殊的幀被放入堆棧中做標記。因此在調用鏈跨越兩個 Assembly/AppDomain 時,堆棧遍歷回調函數將有一個合適的時機,檢測新的 Assembly/AppDomain 是否擁有足夠權限。這兩類檢測思路類似,都是先通過 Assembly::GetSecurityDescriptor 函數 (Assembly.cpp:747) 或 AppDomain::GetSecurityDescriptor 函數 (AppDomain.cpp:1146) 獲取一個安全描述符 SecurityDescriptor;然后對需要進行 CAS 檢測的情況,調用 SecurityDescriptor::GetGrantedPermissionSet 函數 (Security.cpp:2218) 獲得相關權限集;最后調用回調函數傳入參數中的 pfnCheckGrants 函數指針,進行權限驗證。 值得注意的是,當安全描述符被標記為完全可信任 (SecurityDescriptor::IsFullyTrusted())、堆棧遍歷參數指定非受限模式 (IUnrestrictedPermission)、以及 Assembly 是系統 BCL 類庫(mscorlib.dll) 或 AppDomain 是缺省 AppDomain (用于加載 BCL 類庫,具體說明參見《用WinDbg探索CLR世界 [6] AppDomain 的創建過程 》一文),則忽略 CAS 檢測。 對完全可信任概念的含義,可以參考《可怕的 Fully Trusted Code》一文。 如果需要進行 CAS 檢測,則 CheckGrants 函數 (ComCodeAccessSecurityEngine.cpp:128) 將完成權限的驗證工作。而其實際工作,則將通過 Managed 方法 CodeAccessSecurityEngine::CheckHelper 方法 (CodeAccessSecurityEngine.cs:230) 完成。而 CheckHelper 方法將通過權限類型本身的 IsSubsetOf/Intersect 等方法的實現,來判斷 Assembly/AppDomain 現有權限集,是否包括請求的權限。而 Assembly/AppDomain 現有權限集,則是在 Assembly 被載入以及 AppDomain 被創建時,由 CLR Loader 創建的。以后有機會再專門寫篇文章分析這個權限集的構建邏輯。 以下內容為程序代碼: private static void CheckHelper(PermissionSet grantedSet, PermissionSet deniedSet, CodeAccessPermission demand, PermissionToken permToken) { if (permToken == null) permToken = PermissionToken.GetToken(demand); try { // 獲取權限集不能為空 if (grantedSet == null) { throw new SecurityException(...); } // 不處理權限集不受限或請求權限為非受限權限的情況 else if (!grantedSet.IsUnrestricted() || !(demand is IUnrestrictedPermission)) { CodeAccessPermission grantedPerm = (CodeAccessPermission)grantedSet.GetPermission(permToken); if (grantedPerm == null) { if (!demand.IsSubsetOf( null )) throw new SecurityException(String.Format(...); else return; } } // 驗證權限沒有被顯式禁止 if (deniedSet != null) { CodeAccessPermission deniedPerm = (CodeAccessPermission)deniedSet.GetPermission(permToken); if (deniedPerm != null) { if (deniedPerm.Intersect(demand) != null) { throw new SecurityException(...); } } } } catch (Exception e) { // 所有的非 SecurityException 異常將都被轉換為 SecurityException 異常 // 因為這些異常的發生都是因為獲取指定權限操作失敗的原因 if (e is SecurityException) throw e; else throw new SecurityException(...); } } 最后 CodeAccessCheckStackWalkCB 還需要處理顯式指定了安全對象幀的情況。對幀安全對象進行檢測的 CheckFrameData 方法 (ComCodeAccessSecurityEngine.cpp:231) 與 CheckGrants 類似,也是最終通過 CheckHelper 方法實現的,這里就不羅嗦了。堆棧幀的安全對象,等到介紹堆棧結構的時候再詳細解釋。 至此,CLR 中代碼訪問安全檢測的大致實現思路以及比較清晰了,等把堆棧幀結構和 CLR Loader 安全權限集構建的文章弄完,再整理篇完整的,呵呵。 網絡的神奇作用吸引著越來越多的用戶加入其中,正因如此,網絡的承受能力也面臨著越來越嚴峻的考驗―從硬件上、軟件上、所用標準上......,各項技術都需要適時應勢,對應發展,這正是網絡迅速走向進步的催化劑。 |
溫馨提示:喜歡本站的話,請收藏一下本站!