程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# 程序員參考--安全性教學文章

C# 程序員參考--安全性教學文章

編輯:C#入門知識

本教程討論了 .NET Framework 安全性並顯示了在 C# 修改安全權限的兩種方式:命令性安全和聲明性安全。

教程

大多數應用程序和組件開發人員不需完成任何特別的工作就可使用 .NET Framework 安全系統並從它所提供的安全保護中受益。

但“安全庫”是一個例外,它要求了解更多深入的知識並對安全系統加以特殊考慮。這些代碼表明了安全托管代碼與非限制代碼之間的界限,後者如本機代碼(這超出了 .NET Framework 安全基礎結構可以強制的范圍)。這些庫通常必須受到高度信任才可以工作,它們是托管代碼中編程錯誤會潛在地暴露安全隱患的一個位置。代碼訪問安全性無法消除人為錯誤的可能性,但相對於使用幾個安全庫的大量應用程序代碼而言,需要嚴格審查的代碼量將大大減少。

示例

該教程包括下列示例:

  • 示例 1:強制式安全性
  • 示例 2:聲明式安全性
  • 示例 3:禁止安全性

安全性

.NET Framework 安全性通過在托管代碼上強制實施安全限制來防止其他代碼誤用或破壞您的代碼和數據。當 .NET Framework 應用程序請求權限時,由管理員建立的安全策略將授予權限或拒絕運行代碼。信任是基於有關代碼的證據(如數字簽名、代碼來自何處等)的。一旦授予權限,安全性就會實施控制這些代碼可以做什麼(或如果未授予權限,則控制代碼不能做什麼)的權限。

權限

.NET Framework 安全性只有當代碼具有使用受保護資源的“權限”時才允許它使用這些資源。為了表示此情形,.NET Framework 使用了“權限”的概念,它表示代碼訪問受保護資源的權力。代碼請求所需的權限,然後由 .NET Framework 應用的安全策略確定實際授予代碼哪些權限。

.NET Framework 提供了代碼訪問權限類,其中每個類都封裝了訪問某一特定資源的能力。使用這些權限向 .NET Framework 指示需要允許代碼做什麼以及必須授權代碼的調用方做什麼。策略還使用這些對象確定要向代碼授予哪些權限。

策略

安全策略的強制性保證了 .NET Framework 托管代碼的安全。每個加載的程序集都受到安全策略的約束,安全策略基於信任授予代碼權限,而信任又是基於有關代碼的證據的。有關管理安全策略的信息,請參見“閱讀材料列表”中的 .NET Framework 文檔。

在 C# 中請求安全權限

在 C# 中請求安全權限的方法有以下兩種:

  • 強制式:使用對 .NET Framework 中權限類的調用
  • 聲明式:使用安全權限屬性

下面兩個示例說明了這兩種方法。有關請求安全權限的更多信息,請參見要求。

示例 1:強制式安全性

以下示例使用 .NET Framework 調用拒絕 UnmanagedCode 權限。

// ImperativeSecurity.cs



using System;



using System.Security;



using System.Security.Permissions;



using System.Runtime.InteropServices;







class NativeMethods



{



    // This is a call to unmanaged code. Executing this method requires 



    // the UnmanagedCode security permission. Without this permission



    // an attempt to call this method will throw a SecurityException:



    [DllImport("msvcrt.dll")]



    public static extern int puts(string str);



    [DllImport("msvcrt.dll")]



    internal static extern int _flushall();



}







class MainClass



{



    private static void CallUnmanagedCodeWithoutPermission()



    {



        // Create a security permission object to describe the



        // UnmanagedCode permission:



        SecurityPermission perm = 



           new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);







        // Deny the UnmanagedCode from our current set of permissions.



        // Any method that is called on this thread until this method 



        // returns will be denied access to unmanaged code.



        // Even though the CallUnmanagedCodeWithPermission method



        // is called from a stack frame that already



        // calls Assert for unmanaged code, you still cannot call native



        // code. Because you use Deny here, the permission gets 



        // overwritten.



        perm.Deny();







        try



        {



            Console.WriteLine("Attempting to call unmanaged code without permission.");



            NativeMethods.puts("Hello World!");



            NativeMethods._flushall();



            Console.WriteLine("Called unmanaged code without permission. Whoops!");



        }



        catch (SecurityException)



        {



            Console.WriteLine("Caught Security Exception atte

[1] [2] [3] [4] [5] 下一頁  

mpting to call unmanaged code."); } } private static void CallUnmanagedCodeWithPermission() { // Create a security permission object to describe the // UnmanagedCode permission: SecurityPermission perm = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); // Check that you have permission to access unmanaged code. // If you don't have permission to access unmanaged code, then // this call will throw a SecurityException. // Even though the CallUnmanagedCodeWithPermission method // is called from a stack frame that already // calls Assert for unmanaged code, you still cannot call native // code. Because you use Deny here, the permission gets // overwritten. perm.Assert(); try { Console.WriteLine("Attempting to call unmanaged code with permission."); NativeMethods.puts("Hello World!"); NativeMethods._flushall(); Console.WriteLine("Called unmanaged code with permission."); } catch (SecurityException) { Console.WriteLine("Caught Security Exception attempting to call unmanaged code. Whoops!"); } } public static void Main() { // The method itself will call the security permission Deny // for unmanaged code, which will override the Assert permission // in this stack frame. SecurityPermission perm = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); perm.Assert(); CallUnmanagedCodeWithoutPermission(); // The method itself will call the security permission Assert // for unmanaged code, which will override the Deny permission in // this stack frame. perm.Deny(); CallUnmanagedCodeWithPermission(); } }

輸出

Attempting to call unmanaged code without permission.



Caught Security Exception attempting to call unmanaged code.



Attempting to call unmanaged code with permission.



Hello World!



Called unmanaged code with permission.

示例 2:聲明式安全性

這是使用安全權限屬性的同一個示例。

// DeclarativeSecurity.cs



using System;



using System.Security;



using System.Security.Permissions;



using System.Runtime.InteropServices;







class NativeMethods



{



    // This is a call to unmanaged code. Executing this method requires 



    // the UnmanagedCode security permission. Without this permission,



    // an attempt to call this method will throw a SecurityException:



    [DllImport("msvcrt.dll")]



    public static extern int puts(string str);



    [DllImport("msvcrt.dll")]



    internal static extern int _flushall();



}







class MainClass



{



    // The security permission attached to this method will deny the



    // UnmanagedCode permission from the current set of permissions for



    // the duration of the call to this method:



    // Even though the CallUnmanagedCodeWithoutPermission method is



    // called from a stack frame that already calls



    // Assert for unmanaged code, you still cannot call native code.



    // Because this function is attached with the Deny permission for



    // unmanaged code, the permission gets overwritten.



    [SecurityPermission(SecurityAction.Deny, Flags = 



       SecurityPermissionFlag.UnmanagedCode)]



    private static void CallUnmanagedCodeWithoutPermission()



    {



        try



        {



            Console.WriteLine("Attempting to call un

上一頁  [1] [2] [3] [4] [5] 下一頁  

managed code without permission."); NativeMethods.puts("Hello World!"); NativeMethods._flushall(); Console.WriteLine("Called unmanaged code without permission. Whoops!"); } catch (SecurityException) { Console.WriteLine("Caught Security Exception attempting to call unmanaged code."); } } // The security permission attached to this method will force a // runtime check for the unmanaged code permission whenever // this method is called. If the caller does not have unmanaged code // permission, then the call will generate a Security Exception. // Even though the CallUnmanagedCodeWithPermission method is called // from a stack frame that already calls // Deny for unmanaged code, it will not prevent you from calling // native code. Because this method is attached with the Assert // permission for unmanaged code, the permission gets overwritten. [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)] private static void CallUnmanagedCodeWithPermission() { try { Console.WriteLine("Attempting to call unmanaged code with permission."); NativeMethods.puts("Hello World!"); NativeMethods._flushall(); Console.WriteLine("Called unmanaged code with permission."); } catch (SecurityException) { Console.WriteLine("Caught Security Exception attempting to call unmanaged code. Whoops!"); } } public static void Main() { SecurityPermission perm = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); // The method itself is attached with the security permission // Deny for unmanaged code, which will override // the Assert permission in this stack frame. perm.Assert(); CallUnmanagedCodeWithoutPermission(); // The method itself is attached with the security permission // Assert for unmanaged code, which will override the Deny // permission in this stack frame. perm.Deny(); CallUnmanagedCodeWithPermission(); } }

輸出

Attempting to call unmanaged code without permission.



Caught Security Exception attempting to call unmanaged code.



Attempting to call unmanaged code with permission.



Hello World!



Called unmanaged code with permission.

安全性和性能

.NET Framework 安全系統可以防止從網絡上下載的惡意代碼損壞您的計算機系統。但即使代碼從不引發 SecurityException,這些安全檢查也並不是沒有代價的。

通常,公共語言運行庫驗證非托管方法的調用方在運行時是否對每個非托管方法調用都具有非托管代碼訪問權限。這對多次調用非托管代碼的應用程序來說代價可能是非常高的。SuppressUnmanagedCodeSecurityAttribute 可以更改此默認行為。當用該屬性聲明非托管方法時,將在調用該方法的代碼被加載到公共語言運行庫中時檢查安全請求。

安全說明   使用 SuppressUnmanagedCodeSecurityAttribute 時,應格外小心以確保沒有引入安全漏洞。例如,開發人員需要驗證用戶正在安全使用非托管 API 以及調用方無法影響或濫用此調用。開發人員還可以添加適當的請求以確保所有調用方都具有適當的權限。例如,如果對本機代碼進行調用以訪問文件(目的是利用結構化存儲,如擴展文件屬性等),而非托管代碼請求被禁止,則應明確發出一個文件 IO 請求以確保代碼不會被誤用。

示例 3:優化非托管調用

在本例中,對非托管代碼權限的檢查僅在加載時執行一次,而不是在每次調用非托管方法時都執行。如果多次調用非托管方法,則可能極大地提高性能。

// SuppressSecurity.cs



using System;



using System.Security;



using System.Security.Permissions;



using System.Runtime.InteropServices;







class NativeMethods



{



    // This is a call to unmanaged code. Executing this method requires 



    // the UnmanagedCode security permission. Without this permission,



    // an 

上一頁  [1] [2] [3] [4] [5] 下一頁  

attempt to call this method will throw a SecurityException: /* NOTE: The SuppressUnmanagedCodeSecurityAttribute disables the check for the UnmanagedCode permission at runtime. Be Careful! */ [SuppressUnmanagedCodeSecurityAttribute()] [DllImport("msvcrt.dll")] internal static extern int puts(string str); [SuppressUnmanagedCodeSecurityAttribute()] [DllImport("msvcrt.dll")] internal static extern int _flushall(); } class MainClass { // The security permission attached to this method will remove the // UnmanagedCode permission from the current set of permissions for // the duration of the call to this method. // Even though the CallUnmanagedCodeWithoutPermission method is // called from a stack frame that already calls // Assert for unmanaged code, you still cannot call native code. // Because this method is attached with the Deny permission for // unmanaged code, the permission gets overwritten. However, because // you are using SuppressUnmanagedCodeSecurityAttribute here, you can // still call the unmanaged methods successfully. // The code should use other security checks to ensure that you don't // incur a security hole. [SecurityPermission(SecurityAction.Deny, Flags = SecurityPermissionFlag.UnmanagedCode)] private static void CallUnmanagedCodeWithoutPermission() { try { // The UnmanagedCode security check is disbled on the call // below. However, the unmanaged call only displays UI. The // security will be ensured by only allowing the unmanaged // call if there is a UI permission. UIPermission uiPermission = new UIPermission(PermissionState.Unrestricted); uiPermission.Demand(); Console.WriteLine("Attempting to call unmanaged code without UnmanagedCode permission."); NativeMethods.puts("Hello World!"); NativeMethods._flushall(); Console.WriteLine("Called unmanaged code without UnmanagedCode permission."); } catch (SecurityException) { Console.WriteLine("Caught Security Exception attempting to call unmanaged code."); } } // The security permission attached to this method will add the // UnmanagedCode permission to the current set of permissions for the // duration of the call to this method. // Even though the CallUnmanagedCodeWithPermission method is called // from a stack frame that already calls // Deny for unmanaged code, it will not prevent you from calling // native code. Because this method is attached with the Assert // permission for unmanaged code, the permission gets overwritten. // Because you are using SuppressUnmanagedCodeSecurityAttribute here, // you can call the unmanaged methods successfully. // The SuppressUnmanagedCodeSecurityAttribute will let you succeed, // even if you don't have a permission. [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)] private static void CallUnmanagedCodeWithPermission() { try { Console.WriteLine("Attempting to call unmanaged code with permission."); NativeMethods.puts("Hello World!"); NativeMethods._flushall(); Console.WriteLine("Called unmanaged code with permission."); } catch (SecurityException) { Console.WriteLine("Caught Security Exception attempting to call unmanaged code. Whoops!"); } } public static void

上一頁  [1] [2] [3] [4] [5] 下一頁  

Main() { SecurityPermission perm = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); // The method itself is attached with the security permission Deny // for unmanaged code, which will override the Assert permission in // this stack frame. However, because you are using // SuppressUnmanagedCodeSecurityAttribute, you can still call the // unmanaged methods successfully. // The code should use other security checks to ensure that you // don't incur a security hole. perm.Assert(); CallUnmanagedCodeWithoutPermission(); // The method itself is attached with the security permission // Assert for unmanaged code, which will override the Deny // permission in this stack frame. Because you are using // SuppressUnmanagedCodeSecurityAttribute, you can call the // unmanaged methods successfully. // The SuppressUnmanagedCodeSecurityAttribute will let you succeed, // even if you don't have a permission. perm.Deny(); CallUnmanagedCodeWithPermission(); } }

輸出

Attempting to call unmanaged code without UnmanagedCode permission.



Hello World!



Called unmanaged code without UnmanagedCode permission.



Attempting to call unmanaged code with permission.



Hello World!



Called unmanaged code with permission.

代碼討論

請注意,以上示例允許兩個非托管調用都成功,即使第一個調用不具有 UnmanagedCode 權限。在使用 SuppressUnmanagedCodeSecurityAttribute 時,應使用其他安全檢查以確保不會招致安全漏洞。在上面的示例中,通過在非托管調用之前添加 UIPermissionDemand

uiPermission.Demand();

做到這一點,它確保調用方具有顯示 UI 的權限。

 

上一頁  [1] [2] [3] [4] [5] 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved