本示例演示了如何通过权限类和权限属性来修改安全权限
// ImperativeSecurity.cs
using System; using System.Security; using System.Security.Permissions; using System.Runtime.InteropServices; class NativeMethods { // 这是对非托管代码的调用。执行此方法需要 // UnmanagedCode 安全权限。如果没有此权限, // 则调用此方法的尝试将引发 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() { // 创建安全权限对象以描述 // UnmanagedCode 权限: SecurityPermission perm = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); // 拒绝当前权限集中的 UnmanagedCode。 // 在此方法返回之前,在此线程上调用的任何方法 // 都不允许访问非托管代码。 // 即使 CallUnmanagedCodeWithPermission 方法 // 是从已经为非托管代码调用了 // Assert 的堆栈帧调用的,也无法调用本机 // 代码。由于此处使用了 Deny,因此权限 // 被覆盖。 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 attempting to call unmanaged code."); } } private static void CallUnmanagedCodeWithPermission() { // 创建安全权限对象来描述 // UnmanagedCode 权限: SecurityPermission perm = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); // 检查您是否具有访问非托管代码的权限。 // 如果您没有访问非托管代码的权限,则 // 此调用将引发 SecurityException。 // 即使 CallUnmanagedCodeWithPermission 方法 // 是从已经为非托管代码调用了 Assert 的堆栈帧调用的, // 也不能调用本机 // 代码。由于此处使用了 Deny,因此权限被 // 覆盖。 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() { // 该方法本身将为非托管代码调用安全权限 Deny, // 这会重写此堆栈帧中的 Assert // 权限。 SecurityPermission perm = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); perm.Assert(); CallUnmanagedCodeWithoutPermission(); // 该方法本身将为非托管代码调用安全权限 Assert, // 这会重写此堆栈帧中的 Deny // 权限。 perm.Deny(); CallUnmanagedCodeWithPermission(); } }
// DeclarativeSecurity.cs
using System; using System.Security; using System.Security.Permissions; using System.Runtime.InteropServices; class NativeMethods { // 这是对非托管代码的调用。执行此方法需要 // UnmanagedCode 安全权限。如果没有此权限, // 则调用此方法的尝试将引发 SecurityException: [DllImport("msvcrt.dll")] public static extern int puts(string str); [DllImport("msvcrt.dll")] internal static extern int _flushall(); } class MainClass { // 附加到此方法的安全权限在调用此方法 // 期间将拒绝当前权限集中的 // UnmanagedCode 权限: // 即使 CallUnmanagedCodeWithoutPermission 方法是在 // 已经为非托管代码调用了 Assert 的堆栈帧中调用的, // 也无法调用本机代码。 // 由于此函数附加了非托管代码的 Deny 权限, // 因此相应的安全权限被覆盖。 [SecurityPermission(SecurityAction.Deny, Flags = SecurityPermissionFlag.UnmanagedCode)] private static void CallUnmanagedCodeWithoutPermission() { 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 attempting to call unmanaged code."); } } // 每当调用此方法时,附加到此方法的安全权限都强制 // 对非托管代码权限进行 // 运行时检查。如果调用方不具有非托管代码 // 的访问权限,则调用将产生安全异常。 // 即使 CallUnmanagedCodeWithPermission 方法是在 // 已经为非托管代码调用了 // Deny 的堆栈帧中调用的,也不会妨碍您调用 // 本机代码。由于此方法附加了非托管代码的 Assert // 权限,因此相应的安全权限被覆盖。 [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); // 此方法本身附加了非托管代码 // 的 Deny 安全权限,这会重写 // 此堆栈帧中的 Assert 权限。 perm.Assert(); CallUnmanagedCodeWithoutPermission(); // 此方法本身附加了非托管代码 // 的安全权限 Assert,这会重写 // 此堆栈帧中的 Deny 权限。 perm.Deny(); CallUnmanagedCodeWithPermission(); } }
// SuppressSecurity.cs
using System; using System.Security; using System.Security.Permissions; using System.Runtime.InteropServices; class NativeMethods { // 这是对非托管代码的调用。执行此方法需要 // UnmanagedCode 安全权限。如果没有此权限, // 则调用此方法的尝试将引发 SecurityException: /* 注意:SuppressUnmanagedCodeSecurityAttribute 禁止 在运行时检查 UnmanagedCode 权限。一定要小心!*/ [SuppressUnmanagedCodeSecurityAttribute()] [DllImport("msvcrt.dll")] internal static extern int puts(string str); [SuppressUnmanagedCodeSecurityAttribute()] [DllImport("msvcrt.dll")] internal static extern int _flushall(); } class MainClass { // 附加到此方法的安全权限在 // 调用此方法期间将从当前权限集中移除 // UnmanagedCode 权限。 // 即使 CallUnmanagedCodeWithoutPermission 方法是 // 在已经为非托管代码调用了 // Assert 的堆栈帧中调用的,也无法调用本机代码。 // 由于此方法附加了非托管代码的 Deny 权限, // 因此相应的安全权限被覆盖。但是,由于 // 此处使用的是 SuppressUnmanagedCodeSecurityAttribute,因此 // 仍可以成功调用非托管方法。 // 该代码应使用其他安全检查方法,以确保不会 // 出现安全漏洞。 [SecurityPermission(SecurityAction.Deny, Flags = SecurityPermissionFlag.UnmanagedCode)] private static void CallUnmanagedCodeWithoutPermission() { try { // UnmanagedCode 安全检查在下面的调用中 // 被禁用。但非托管调用仅显示用户界面。 // 如果存在用户界面权限,则通过只允许非托管 // 调用可以确保安全。 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."); } } // 附加到此方法的安全权限在调用此方法 // 期间将 UnmanagedCode // 权限添加到当前权限集中。 // 即使 CallUnmanagedCodeWithPermission 方法是 // 在已经为非托管代码调用了 // Deny 的堆栈帧中调用的,也不会妨碍您调用 // 本机代码。由于此方法附加了非托管代码的 Assert 权限, // 因此相应的安全权限被覆盖。 // 由于此处使用的是 SuppressUnmanagedCodeSecurityAttribute,因此 // 可以成功调用非托管方法。 // 即使您没有权限, // SuppressUnmanagedCodeSecurityAttribute 也会使操作成功。 [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); // 该方法本身附加了非托管代码 // 的安全权限 Deny,这会重写 // 此堆栈帧中的 Assert 权限。但是,由于使用的是 // SuppressUnmanagedCodeSecurityAttribute,因此仍可以成功调用 // 非托管方法。 // 该代码应使用其他安全检查方法,以确保 // 不会出现安全漏洞。 perm.Assert(); CallUnmanagedCodeWithoutPermission(); // 该方法本身附加了非托管代码 // 的安全权限 Assert,这会重写 // 此堆栈帧中的 Deny 权限。由于此处使用的是 // SuppressUnmanagedCodeSecurityAttribute,因此可以成功调用 // 非托管方法。 // 即使您没有权限, // SuppressUnmanagedCodeSecurityAttribute 也会使操作成功。 perm.Deny(); CallUnmanagedCodeWithPermission(); } }