Visual Basic .NET 和 Visual C# .Net 程序員需要解決的安全問題
Robin Reynolds-Haertle
Visual Studio Team
Microsoft Corporation
2002 年 1 月
摘要:本文著重討論了 Visual Basic .NET 和 Visual C# .NET 開發人員在開始使用 .Net 框架時需要解決的主要安全問題。此概述討論了 Windows 應用程序和 Web 應用程序,以及開發過程的實現、調試和部署階段。
本文適用於 Visual Studio .NET 和 .Net 框架的最終版本。如果您使用的是預發布版本,則其中應用程序的運行可能與本文所討論的略有不同。
目錄
- 簡介
- 代碼訪問安全性
- 完全信任
- 部分信任
- 部分信任環境的開發
- 測試
- 其他資源
- Web 應用程序
- 動態發現
- 身份驗證、模擬和委托
- ASPNET 進程標識
- 在 ASPNET 標識下運行時保護文件資源的安全
- 使用 ASPNET 標識進行調試
- Visual Studio .Net 開發環境中的安全機制
- 總結
簡介
與早期版本的 Visual Studio 相比,Microsoft® Visual Studio® .NET 為應用程序的運行提供了更好的安全控制。.Net 框架提供了更多的控制,同時也要求您承擔更多的編程責任。在為用戶創建友好易用的應用程序時,您需要解決一些安全問題。
通常在以下三種情況下需要解決安全問題:
- 運行您的應用程序的用戶可能拒絕該應用程序的權限,因為應用程序所運行的位置已被指定為拒絕該用戶訪問某些系統資源。例如,用戶可以通過配置公共語言運行時來拒絕存儲在網絡驅動器上的所有應用程序的文件權限。您在編寫代碼時應注意此問題,並且應編寫代碼對這種拒絕作出恰當的回應。
- 需要防止從您的 Web 服務器訪問 Web 應用程序的用戶在服務器上運行惡意代碼或破壞數據。
- Visual Studio 的設置方式將或多或少地使服務器面臨受到惡意代碼攻擊的危險。
代碼訪問安全性
代碼訪問安全性是 .NET 框架的一個系統,它通過控制代碼的執行來控制對資源的訪問。這種安全功能獨立於操作系統提供的安全性,並且是對操作系統提供的安全性的補充。當用戶運行您的應用程序時,應用程序將由 .Net 公共語言運行時分配到五個區域之一。這五個區域是:
- 我的電腦 - 用戶計算機上的應用程序。
- 本地 Intranet - 用戶的 Intranet 上的應用程序。
- Internet - 來自 Internet 的應用程序。
- 可信站點 - 來自由 Internet Explorer 定義為“可信”站點的應用程序。
- 不可信站點 - 來自由 Internet Explorer 定義為“受限”站點的應用程序。
上述每個區域都由系統管理員設置了特定的訪問權限。可以將每個區域的安全級別設置為完全信任、中級信任、低級信任或不信任。信任級別定義了應用程序可以訪問的資源。區域與其他安全憑證(例如發布者、強名稱、Web 站點以及代碼的 URL)一起確定在運行時授予該代碼的權限。您無法控制用戶計算機上的安全設置,但您的應用程序在運行時仍會受到即時設置的限制。這就意味著應用程序可能會被拒絕訪問某些特定資源。例如,應用程序可能需要將數據寫入文件,但用戶的系統將通過引發異常而拒絕在運行時進行寫入訪問。有關安全憑證的詳細信息,請參閱 Evidence(英文)。
您的工作就是開發應用程序來處理這種情況。這並不表示讓您的應用程序用另外一種方法來寫入數據,而是說您的應用程序應該預計到可能無法寫入數據,然後對這種可能性作出響應。您可能需要使用更多的異常處理(Visual Basic 中的 Try...Catch 或 C# 中的 try...catch)或 System.Security.Permissions 命名空間中的某些對象,以使應用程序代碼更加可靠。本文後面“部分信任環境的開發”一節對這些方法進行了簡要說明。
區域的安全級別可以通過隨 .Net 框架一起安裝的“管理工具”來進行設置。有關在計算機上設置區域安全級別的詳細信息,請參閱 Administration Tools(英文)。
完全信任
開發人員通常在完全信任環境中工作。他們將源代碼存放在硬盤驅動器上,並在用於開發的計算機上對其應用程序進行測試。在這種完全信任環境中,開發人員編譯的任何代碼都可以在本地計算機上運行。由於本地計算機被默認定義為完全信任環境,因此不會出現安全異常。
部分信任
部分信任是指完全信任區域以外的所有區域。部署應用程序時,應用程序可能會移至新的區域,而新區域可能不完全信任應用程序。在部分信任環境中運行代碼的兩種最常見的情況是:
- 運行從 Internet 下載的代碼。
- 運行駐留在網絡共享位置 (Intranet) 的代碼。
在部分信任區域中可能會被拒絕訪問的資源示例包括:
- 文件 I/O,包括文件的讀取、寫入、創建、刪除或打印。
- 系統組件,如注冊表值和環境變量。
- 服務器組件,包括目錄服務、注冊表、事件日志、性能計數器和消息隊列。
在部分信任環境中哪些內容是不允許的呢?這不太容易確定。.Net 框架中的每個類以及每個類中的每種方法都有一個安全屬性,用於定義運行該方法所需的信任級別,並且正是由於這些安全功能,使得在運行時可能無法訪問該屬性。區域級別並不只是信任級別到屬性的簡單映射,而是一個授予特定類和方法的特定權限的集合。您的應用程序無法只是簡單地查詢信任級別然後就可以預計哪些資源不可用。您可以確定應用程序是否在完全信任環境中運行。在下一節“部分信任環境的開發”中,我們將介紹一種方法。
部分信任環境的開發
本節簡要介紹了安全問題可能會對編寫的代碼產生什麼樣的影響。部分信任環境的開發沒有單一的解決方案。您的解決方案取決於您所編寫的應用程序。此外,由於信任級別在應用程序的執行過程中可能會發生變化,因此不能僅測試現有的信任級別,然後就繼續執行。
開發部分信任區域的第一步是編寫能夠識別即將發生安全異常的代碼。請注意以下代碼:' Visual BasicPublic Sub MakeABitmap() Dim b As Bitmap = New Bitmap(100, 100) ' 此處的代碼將以位圖格式繪制一張漂亮的圖片 b.Save("c:\PrettyPicture.bmp")End Sub// C#public void MakeABitmap(){ Bitmap b = new Bitmap(100, 100); // 此處的代碼將以位圖格式繪制一張漂亮的圖片 b.Save("c:\\PrettyPicture.bmp");}
如果項目和項目程序集存儲在您計算機的硬盤驅動器上,並且您是計算機 Administrators 組的成員,則此方法在運行時不會引發異常。如果將此應用程序部署到您的 Intranet,則當應用程序試圖保存位圖對象時,將引發 System.Security.SecurityException(請參閱 SecurityException Class [英文])。如果此代碼周圍沒有 Try...Catch(在 Visual Basic 中)或 try...catch(在 C# 中)塊,則應用程序將因異常而終止。這會令用戶感到不滿意。如果您添加異常處理代碼,應用程序就能夠:
- 警告用戶應用程序無法完成所有需要完成的任務。
- 清除所有現有對象,以便 catch 塊後面的代碼能夠成功運行。
您可以按如下所示修改保存位圖的代碼。添加的代碼將警告用戶該文件因安全性被拒絕而未能保存,從而將安全性失敗與文件 I/O 失敗(例如不正確的文件名)區分開來。這種方法不會產生任何安全漏洞。用戶應修改安全設置以信任您的應用程序,否則應用程序將不會運行。' Visual BasicPublic Sub MakeABitmap() Dim b As Bitmap Try b = New Bitmap(100, 100) b.Save("c:\PrettyPicture.bmp") Catch ex As System.Security.SecurityException ' 告知用戶保存失敗。 MessageBox.Show("拒絕授予保存該文件的權限," & _ "未保存此位圖。") Catch ex As System.Exception ' 此處對其他異常作出反應。 MessageBox.Show(ex.Message) End TryEnd Sub// C#public void MakeABitmap(){ Bitmap b = null; try { b = new Bitmap(100, 100); b.Save("c:\\PrettyPicture.bmp"); } catch (System.Security.SecurityException ex) { // 告知用戶保存失敗。 MessageBox.Show("拒絕授予保存該文件的權限," + "未保存此位圖。"); } catch (System.Exception ex) { // 此處對其他異常作出反應。 MessageBox.Show(ex.Message); }}
使用 System.Security.Permissions(英文)命名空間中的類、屬性和枚舉,可以對應用程序中安全任務進行更多的控制。如果您在編寫可從其他應用程序調用的庫,則可以讓庫驗證調用代碼的權限。例如,您只需在代碼文件的頂部添加以下程序集級別的屬性。加載該程序集時,運行時將驗證權限。如果運行時拒絕所請求的權限,程序集將無法加載並且將引發一個安全異常。如果向獨立的應用程序添加此屬性,則應用程序可能不會運行。如果此屬性出現在類庫中,則可能不會在運行時加載該庫。您需要在調用此類庫的代碼中添加 try/catch 塊。' Visual Basic<Assembly: System.Security.Permissions.FileIOPermissionAttribute( _SecurityAction.RequestMinimum, Write:="c:\PrettyPicture.bmp")> // C#[assembly: System.Security.Permissions.FileIOPermissionAttribute(SecurityAction.RequestMinimum, Write="c:\\PrettyPicture.bmp")]
您也可以專門向運行時請求權限,下面的示例中使用了 Demand 方法。運行時可能允許或拒絕該請求。拒絕請求是通過引發安全異常來實現的。您可以按如下所示重新編寫代碼,以明確請求寫入位圖文件的權限:' Visual BasicPublic Sub MakeABitmap() Dim filename As String = "c:\PrettyPicture.bmp" Dim permission As FileIOPermission = _ New FileIOPermission(FileIOPermissionAccess.Write, _ filename) Dim b As Bitmap = Nothing Try b = New Bitmap(100, 100) permission.Demand() b.Save(filename) Catch ex As System.Security.SecurityException ' 告知用戶保存失敗。 MessageBox.Show("拒絕授予保存該文件的權限," & _ "未保存此位圖。") Catch ex As System.Exception ' 此處對其他異常作出反應。 MessageBox.Show(ex.Message) End TryEnd Sub// C#using System.Security.Permissions;public void MakeABitmap(){ string filename = "c:\\PrettyPicture.bmp"; FileIOPermission permission = new FileIOPermission(FileIOPermissionAccess.Write, filename); Bitmap b = null; try { b = new Bitmap(100, 100); permission.Demand(); b.Save(filename); } catch (System.Security.SecurityException ex) { // 告知用戶保存失敗。 MessageBox.Show("拒絕授予保存該文件的權限," + "未保存此位圖。"); } catch (System.Exception ex) { // 此處對其他異常作出反應。 MessageBox.Show(ex.Message); }}
測試
開發部分信任區域的第二步是在多個環境中進行測試,尤其是在您的 Intranet 和 Internet 上。這將強制引發安全異常。