天天看點

對ASP.NET網站執行代碼覆寫率測試發生System.Security.VerificationException異常的解決方案

當你對ASP.NET 4.0網站執行代碼覆寫率測試時,可能會遇到下面這個異常:

System.Security.VerificationException: Operation could destabilize the runtime.

一般來說,VerificiationException都是關于代碼通路安全(CAS)的問題,.NET在執行托管代碼之前,首先會驗證這個托管程式的強簽名,通過确定其來源來判定該托管程式應該擁有的權限。比如說,如果托管程式是微軟公司的簽名,我們當然是無比的信任它—除非你不用Windows作業系統。機器管理者也可以依據托管程式的來源來決定該托管程式應該擁有的權限,例如讀磁盤檔案、操作系統資料庫這些操作都是可以配置的權限。比方說,管理者可以在機器上設定,由360以及QQ發行的托管程式,隻能通路顯示卡(繪制界面)以及讀寫網絡,而不能執行通路磁盤檔案等操作。

執行代碼安全的前提是,整個程式完全是由托管代碼寫成的,如果托管代碼裡混合非托管代碼,無論是通過托管C++寫成的,還是裡面執行了平台調用(P/Invoke)。就破壞規矩了,因為非托管代碼可以使用指針操作,以及調用其它非托管代碼的方式,甚至—啟動一個程序,然後将原來的托管程式殺掉。是以,進行代碼通路安全的前提條件是,整個應用程式都是使用托管代碼寫成的,為了保證這個前提條件,CLR在執行托管程式之前,首先會驗證程式是否滿足—整個程式都是用托管代碼編寫這一條件。如果不滿足這個條件,那麼CLR會扔出VerificationException,中斷托管程式的執行,在.NET SDK裡,你可以通過PEVerify.exe這個程式驗證一個程式是否可以通過這個驗證。

當然,你可能會說,很多本機運作的托管程式,即使調用了非托管代碼,例如執行了一個平台調用,還是可以照常執行啊。那是因為,當你的程式使用了/unsafe編譯選項時,C#編譯器會自動在托管程式添加上SuppressUnmanagedCodeSecurityAttribute這個屬性,這個屬性告訴CLR。如果程式是在本機執行,那麼就跳過驗證是否調用了非托管代碼這一環節。有興趣的讀者可以把調用非托管代碼的托管程式放在一個網絡路徑上,從那裡執行,應該就可以看到SecurityException了。

在2.0的時候,你可能還不會碰到這個問題,但是在4.0裡面,你就很有可能碰到這個問題—特别是在網站運作在IIS下的話,經常發生。

既然道理已經明白了,修複起來也很容易:

将網站,以及所有需要做代碼覆寫率的裝配件(Assembly)—也就是被vsinstr.exe處理過的裝配件(Assembly),在它們的源代碼(既然你要收集代碼覆寫率,那肯定是由源代碼的)裡的AssemblyInfo.cs裡,加上下面這一行

[assembly: SecurityRules(SecurityRuleSet.Level1, SkipVerificationInFullTrust=true)]

然後在網站的web.config裡,做如下修改(這個選項也可以通過IISAdmin.exe修改):

 <system.web>

    <trust level="Medium" />

     …

 </system.web>

說明,SecurityRules這個屬性,告訴CLR,這個裝配件(Assembly)有自定義的安全機制,SecurityRuleSet.Level1說明采用.NET 2.0下面的安全驗證政策,SkipVerificationInFullTrust告訴CLR,隻有網站運作在FullTrust模式下,才可以跳過安全驗證。最後第二步就是将網站的運作模式改在FullTrust模式下。

本文轉自 donjuan 部落格園部落格,原文連結:   http://www.cnblogs.com/killmyday/archive/2010/11/16/1878847.html,如需轉載請自行聯系原作者

繼續閱讀