作為一名.Net開發人員,你沒日沒夜地寫代碼,你的組件運行在越來越多的機器上。忽然有一天,你發現你寫的組件被引用在別人寫的項目裡,而且最可氣的是,那人竟用你的名義在做破壞它人系統的惡事!你忍不住了,大叫一聲Oh shit!,然後打開MSDN,看看有什麼辦法能幫助你阻止這場陰謀。
OK,辦法找到了,那就是.Net平台提供的Code Access Security有大量繼承於CodeAccessPermission的類可以幫你實現不同方面、不同范圍的代碼安全控制。你所需要做的只是從中挑出最適合的類別加以應用,從而達到保護你的組件的目的。
在經過一番挑選之後,你最終確定了使用StrongNameIdentityPermissionAttribute類。這個類允許你將組件(或類、方法)與某一強名稱(通常就是你發布程序時所用的強名稱)綁定,這樣,只有在客戶端程序具有該強名稱簽名的情況下才能使用你的組件。也就是說,除了你自己編寫的客戶端代碼因為擁有同樣的簽名而被允許使用組件以外,任何第三方代碼都無法通過StrongNameIdentityPermissionAttribute的防護,因此也就無法惡意調用你的組件了:)。聽起來真的不錯,馬上就動手做吧!
為了簡便起見,先創建一個很簡單的Class Library項目,代碼如下:
以下為引用的內容:現在的這個組件非常可憐,因為任何人都可以寫代碼來調用它。下面,你就要耍點手段了:):
首先引入System.Security.Permissions命名空間:
以下為引用的內容:然後,在組件級加上StrongNameIdentityPermissionAttribute屬性:
以下為引用的內容:注意,這裡使用了SecurityAction.RequestMinimum,這申明除非獲得StrongNameIdentityPermissionAttribute所表明的資源訪問權限(即對SecureComp.dll組件的訪問權限,可以把SecureComp.dll看作一樣資源),否則CLR不會准許調用方(即客戶端代碼)訪問所請求的資源;此外,在PublicKey屬性中加入了你所允許的公匙(Public Key)的十六進制表示(轉化成字符串類型)。CRL在運行期間將依照這一段公匙來判斷調用方是否合法,除非調用方擁有相應的私匙(Private Key),否則將無法訪問。看來,平時一定要倍加保護你的密鑰文件,因為密鑰文件(特別是private key)的洩露將會成為你無盡惡夢的根源,而延遲簽名(delay signing)在這裡也就顯得格外重要了:)
說到這裡,你一定會有個大大的問號:這長長的一串PublicKey是怎麼得出來的?難道要我憑空湊出來不成?當然不是。還記得那個Sn.exe工具嗎?通過它就可以把PublicKey給提取出來。OK,打開你的命令行,定位到密鑰文件所在目錄並輸入以下內容:
以下為引用的內容:這樣,提取出來的公匙信息就被存儲在PublicKey.snk文件中。你現在只需把公匙信息讀取出來並轉化成適當的格式就可以了。這裡,你可以使用。NET Framework自帶的Secutil.exe工具,但據我所了解,Secutil工具的輸出都是數組格式(我在自己的機器上測試了Secutil所提供的全部輸出選項,但所得結果都是一樣,這讓我很感意外,不知大家是否有更好的辦法),因此就動手自己寫了一個小工具來完成這一讀取和轉換。大家如果感興趣可以發郵件給我(因為我沒有自己的網絡空間可以存放。當然你也可以自己來寫,因為它實在是太簡單了,就是讀取二進制文件)。
好了,現在你的代碼就被全副武裝起來了。試著寫一個Console客戶端來調用SecureComp,結果怎麼樣?是不是“無法獲得相應權限”?試著用Key.snk給客戶端程序簽名後再訪問,這回可以訪問了吧!:)
結論:適當地應用Code Access Security可以使你的代碼被保護起來,不致被第三方不正確調用;但是過多的安全保護也將造成代碼運行效率下降,從而帶來負面影響。