linux assert 自动打印堆栈,使用 Assert 方法

使用 Assert 方法Using the Assert Method

03/30/2017

本文内容

注意

代码访问安全性 (CA) 和部分受信任代码Code Access Security (CAS) and Partially Trusted Code

.NET Framework 提供一种机制,对在相同应用程序中运行的不同代码强制实施不同的信任级别,该机制称为代码访问安全性 (CAS)。The .NET Framework provides a mechanism for the enforcement of varying levels of trust on different code running in the same application called Code Access Security (CAS).

.NET Core、.NET 5 或更高版本中不支持 CAS。低于7.0 的 c # 版本不支持 CAS。CAS is not supported in .NET Core, .NET 5, or later versions. CAS is not supported by versions of C# later than 7.0.

.NET Framework 中的 CAS 不应作为一种机制,用于根据代码来源或其他标识方面强制实施安全边界。CAS in .NET Framework should not be used as a mechanism for enforcing security boundaries based on code origination or other identity aspects. CA 和 Security-Transparent 代码不支持用作部分受信任的代码(尤其是未知来源的代码)的安全边界。CAS and Security-Transparent Code are not supported as a security boundary with partially trusted code, especially code of unknown origin. 建议在未实施其他安全措施的情况下,不要加载和执行未知来源的代码。We advise against loading and executing code of unknown origins without putting alternative security measures in place. .NET Framework 不会为可能会针对 CAS 沙盒发现的任何特权提升攻击发出安全修补程序。.NET Framework will not issue security patches for any elevation-of-privilege exploits that might be discovered against the CAS sandbox.

此策略适用于 .NET Framework 的所有版本,但不适用于 Silverlight 中所含的 .NET Framework。This policy applies to all versions of .NET Framework, but does not apply to the .NET Framework included in Silverlight.

Assert 是一种可在代码访问权限类和 PermissionSet 类上调用的方法。Assert is a method that can be called on code access permission classes and on the PermissionSet class. 您可以使用Assert来使您的代码 (和下游调用方) 执行您的代码有权执行的操作,但其调用方可能无权执行此操作。You can use Assert to enable your code (and downstream callers) to perform actions that your code has permission to do but its callers might not have permission to do. 安全断言会更改在安全检查期间运行时所执行的正常过程。A security assertion changes the normal process that the runtime performs during a security check. 断言权限时,它会通知安全系统不检查断言权限的代码的调用方。When you assert a permission, it tells the security system not to check the callers of your code for the asserted permission.

注意

请谨慎使用断言,因为它们会打开安全漏洞并破坏运行时强制执行安全限制的机制。Use assertions carefully because they can open security holes and undermine the runtime's mechanism for enforcing security restrictions.

当库调用非托管代码或所执行的调用需要与库的预期用途不明显关联的权限时,断言非常有用。Assertions are useful in situations in which a library calls into unmanaged code or makes a call that requires a permission that is not obviously related to the library's intended use. 例如,调用到非托管代码的所有托管代码都必须具有指定了UnmanagedCode标志的SecurityPermission 。For example, all managed code that calls into unmanaged code must have SecurityPermission with the UnmanagedCode flag specified. 默认情况下,如果代码不是来自本地计算机(如从本地 intranet 下载的代码),则不会对其授予此权限。Code that does not originate from the local computer, such as code that is downloaded from the local intranet, will not be granted this permission by default. 因此,为了使从本地 intranet 下载的代码能调用使用非托管代码的库,它必须具有由该库断言的权限。Therefore, in order for code that is downloaded from the local intranet to be able to call a library that uses unmanaged code, it must have the permission asserted by the library. 此外,某些库可能会执行对调用方不可见且需要特殊权限的调用。Additionally, some libraries might make calls that are unseen to callers and require special permissions.

在代码以对调用方完全不可见的方式访问资源时,也可使用断言。You can also use assertions in situations in which your code accesses a resource in a way that is completely hidden from callers. 例如,假设你的库从数据库获取信息,但在此过程中还会从计算机注册表读取信息。For example, suppose your library acquires information from a database, but in the process also reads information from the computer registry. 由于使用您的库的开发人员不能访问您的源,因此他们无法知道其代码需要system.security.permissions.registrypermission> 才能使用您的代码。Because developers using your library do not have access to your source, they have no way of knowing that their code requires RegistryPermission in order to use your code. 在此情况下,如果你决定要求代码调用方有权访问注册表是不合理或不必要的,你可以断言权限以读取注册表。In this case, if you decide that it is not reasonable or necessary to require that callers of your code have permission to access the registry, you can assert permission for reading the registry. 在这种情况下,适合库断言权限,使没有system.security.permissions.registrypermission> 的调用方可以使用库。In this situation, it is appropriate for the library to assert the permission so that callers without RegistryPermission can use the library.

仅当断言权限和下游调用方所需的权限属于同一类型且要求的权限是断言权限的子集时,断言才会影响堆栈审核。The assertion affects the stack walk only if the asserted permission and a permission demanded by a downstream caller are of the same type and if the demanded permission is a subset of the asserted permission. 例如,如果你将FileIOPermission声明为读取 C 驱动器上的所有文件,并且FileIOPermission读取 C:\Temp 中的文件,则断言可能会影响堆栈审核;但是,如果要求FileIOPermission写入 C 驱动器,则断言不起作用。For example, if you assert FileIOPermission to read all files on the C drive, and a downstream demand is made for FileIOPermission to read files in C:\Temp, the assertion could affect the stack walk; however, if the demand was for FileIOPermission to write to the C drive, the assertion would have no effect.

若要执行断言,必须向你的代码授予正在断言的权限以及表示有权执行断言的 SecurityPermission。To perform assertions, your code must be granted both the permission you are asserting and the SecurityPermission that represents the right to make assertions. 虽然你可以断言尚未授予代码的权限,但此断言毫无意义,因为安全检查在断言使其成功之前就会失败。Although you could assert a permission that your code has not been granted, the assertion would be pointless because the security check would fail before the assertion could cause it to succeed.

下图显示了使用Assert时会发生的情况。The following illustration shows what happens when you use Assert. 假设以下语句针对程序集 A、B、C、E 和 F 以及 P1 和 P1A 两个权限为 true:Assume that the following statements are true about assemblies A, B, C, E, and F, and two permissions, P1 and P1A:

P1A 表示读取 C 驱动器上的 .txt 文件的权限。P1A represents the right to read .txt files on the C drive.

P1 表示读取 C 驱动器上所有文件的权限。P1 represents the right to read all files on the C drive.

P1A 和 P1 均为FileIOPermission类型,而 P1A 是 P1 的子集。P1A and P1 are both FileIOPermission types, and P1A is a subset of P1.

已向程序集 E 和 F 授予了 P1A 权限。Assemblies E and F have been granted P1A permission.

已向程序集 C 授予了 P1 权限。Assembly C has been granted P1 permission.

尚未向程序集 A 和 B 授予 P1 或 P1A 权限。Assemblies A and B have been granted neither P1 nor P1A permissions.

方法 A 包含在程序集 A 中,方法 B 包含在程序集 B 中,依次类推。Method A is contained in assembly A, method B is contained in assembly B, and so on.

b9bed8e77746e5bbe3bc61ce8ec762f4.gif

在这种情况下,方法 A 调用 B,B 调用 C,C 调用 E,E 调用 F。方法 C 断言权限读取 C 驱动器上的文件 (权限 P1) ,而方法 E 要求权限读取 C 驱动器上的 .txt 文件 (权限 P1A) 。In this scenario, method A calls B, B calls C, C calls E, and E calls F. Method C asserts permission to read files on the C drive (permission P1), and method E demands permission to read .txt files on the C drive (permission P1A). 当在运行时遇到 F 中的请求时,将执行堆栈遍历来检查 F 的所有调用方的权限,从 E. E 获得 P1A 权限,因此堆栈审核会继续检查 C 的权限,其中发现 C 的断言。When the demand in F is encountered at run time, a stack walk is performed to check the permissions of all callers of F, starting with E. E has been granted P1A permission, so the stack walk proceeds to examine the permissions of C, where C's assertion is discovered. 因为要求的权限 (P1A) 是断言的权限 (P1) 的子集,所以堆栈审核将停止且安全检查会自动成功。Because the demanded permission (P1A) is a subset of the asserted permission (P1), the stack walk stops and the security check automatically succeeds. 未向程序集 A 和 B 授予权限 P1A 并不重要。It does not matter that assemblies A and B have not been granted permission P1A. 通过断言 P1,方法 C 确保其调用方可以访问受 P1 保护的资源,即使尚未授予调用方访问该资源的权限也是如此。By asserting P1, method C ensures that its callers can access the resource protected by P1, even if the callers have not been granted permission to access that resource.

如果你设计一个类库且某个类访问受保护的资源,则在大多数情况下,你应该提出安全要求,要求此类的调用方拥有适当的权限。If you design a class library and a class accesses a protected resource, you should, in most cases, make a security demand requiring that the callers of the class have the appropriate permission. 如果类随后执行你知道其大多数调用方不具有权限的操作,并且你愿意承担让这些调用方调用你的代码的责任,则可以通过对表示代码正在执行的操作的权限对象调用assert方法来断言权限。If the class then performs an operation for which you know most of its callers will not have permission, and if you are willing to take the responsibility for letting these callers call your code, you can assert the permission by calling the Assert method on a permission object that represents the operation the code is performing. 以这种方式使用断言可以使通常不能调用你的代码的调用方。Using Assert in this way lets callers that normally could not do so call your code. 因此,如果你断言了一个权限,应确保预先执行了适当的安全检查,以防止你的组件被误用。Therefore, if you assert a permission, you should be sure to perform appropriate security checks beforehand to prevent your component from being misused.

例如,假设你的高度受信任的库类具有删除文件的方法。For example, suppose your highly trusted library class has a method that deletes files. 它通过调用非托管的 Win32 函数来访问文件。It accesses the file by calling an unmanaged Win32 function. 调用方调用你的代码的Delete方法,并传入要删除的文件的名称,C:\Test.txt。A caller invokes your code's Delete method, passing in the name of the file to be deleted, C:\Test.txt. 在Delete方法中,你的代码将创建一个对象,该 FileIOPermission 对象表示对 C:\Test.txt 的写访问。Within the Delete method, your code creates a FileIOPermission object representing write access to C:\Test.txt. 需要 (写入访问权限才能删除文件。 ) 你的代码,通过调用FileIOPermission对象的要求方法来调用命令性安全检查。(Write access is required to delete a file.) Your code then invokes an imperative security check by calling the FileIOPermission object's Demand method. 如果调用堆栈中的某个调用方不具有此权限,则会引发 SecurityException。If one of the callers in the call stack does not have this permission, a SecurityException is thrown. 如果未引发任何异常,你会知道所有调用方都有权限访问 C:\Test.txt。If no exception is thrown, you know that all callers have the right to access C:\Test.txt. 由于你认为大多数调用方不具有访问非托管代码的权限,因此你的代码会创建一个 SecurityPermission 对象,该对象表示调用非托管代码和调用该对象的断言方法的权限。Because you believe that most of your callers will not have permission to access unmanaged code, your code then creates a SecurityPermission object that represents the right to call unmanaged code and calls the object's Assert method. 最后,它会调用非托管的 Win32 函数来删除 C:\Text.txt,并将控件返回给调用方。Finally, it calls the unmanaged Win32 function to delete C:\Text.txt and returns control to the caller.

注意

你必须确保你的代码在以下情况下不使用断言:其他代码可使用你的代码来访问由你正在断言的权限所保护的资源。You must be sure that your code does not use assertions in situations where your code can be used by other code to access a resource that is protected by the permission you are asserting. 例如,在写入文件(其名称由调用方指定为参数)的代码中,你将不会断言FileIOPermission来写入文件,因为你的代码将被第三方滥用。For example, in code that writes to a file whose name is specified by the caller as a parameter, you would not assert the FileIOPermission for writing to files because your code would be open to misuse by a third party.

使用命令性安全语法时,对同一方法中的多个权限调用Assert方法会引发安全异常。When you use the imperative security syntax, calling the Assert method on multiple permissions in the same method causes a security exception to be thrown. 相反,应创建PermissionSet对象,向其传递要调用的单个权限,然后调用PermissionSet对象上的Assert方法。Instead, you should create a PermissionSet object, pass it the individual permissions you want to invoke, and then call the Assert method on the PermissionSet object. 使用声明性安全语法时,可以多次调用断言方法。You can call the Assert method more than once when you use the declarative security syntax.

下面的示例演示了使用Assert方法重写安全检查的声明性语法。The following example shows declarative syntax for overriding security checks using the Assert method. 请注意,来语法采用两个值:一个 SecurityAction 枚举,以及要向其授予权限的文件或目录的位置。Notice that the FileIOPermissionAttribute syntax takes two values: a SecurityAction enumeration and the location of the file or directory to which permission is to be granted. Assert C:\Log.txt 即使不检查调用方是否有权访问该文件,调用断言也会导致访问权限成功。The call to Assert causes demands for access to C:\Log.txt to succeed, even though callers are not checked for permission to access the file.

Option Explicit

Option Strict

Imports System

Imports System.IO

Imports System.Security.Permissions

Namespace LogUtil

Public Class Log

Public Sub New()

End Sub

Public Sub

MakeLog()

Dim TextStream As New StreamWriter("C:\Log.txt")

TextStream.WriteLine("This Log was created on {0}", DateTime.Now) '

TextStream.Close()

End Sub

End Class

End Namespace

namespace LogUtil

{

using System;

using System.IO;

using System.Security.Permissions;

public class Log

{

public Log()

{

}

[FileIOPermission(SecurityAction.Assert, All = @"C:\Log.txt")]

public void MakeLog()

{

StreamWriter TextStream = new StreamWriter(@"C:\Log.txt");

TextStream.WriteLine("This Log was created on {0}", DateTime.Now);

TextStream.Close();

}

}

}

下面的代码片段演示了使用Assert方法重写安全检查的命令性语法。The following code fragments show imperative syntax for overriding security checks using the Assert method. 在此示例中,声明了FileIOPermission对象的实例。In this example, an instance of the FileIOPermission object is declared. 其构造函数被传递FileIOPermissionAccess以定义允许的访问类型,后跟描述文件位置的字符串。Its constructor is passed FileIOPermissionAccess.AllAccess to define the type of access allowed, followed by a string describing the file's location. 定义FileIOPermission对象后,只需调用其Assert方法来重写安全检查。Once the FileIOPermission object is defined, you only need to call its Assert method to override the security check.

Option Explicit

Option Strict

Imports System

Imports System.IO

Imports System.Security.Permissions

Namespace LogUtil

Public Class Log

Public Sub New()

End Sub 'New

Public Sub MakeLog()

Dim FilePermission As New FileIOPermission(FileIOPermissionAccess.AllAccess, "C:\Log.txt")

FilePermission.Assert()

Dim TextStream As New StreamWriter("C:\Log.txt")

TextStream.WriteLine("This Log was created on {0}", DateTime.Now)

TextStream.Close()

End Sub

End Class

End Namespace

namespace LogUtil

{

using System;

using System.IO;

using System.Security.Permissions;

public class Log

{

public Log()

{

}

public void MakeLog()

{

FileIOPermission FilePermission = new FileIOPermission(FileIOPermissionAccess.AllAccess,@"C:\Log.txt");

FilePermission.Assert();

StreamWriter TextStream = new StreamWriter(@"C:\Log.txt");

TextStream.WriteLine("This Log was created on {0}", DateTime.Now);

TextStream.Close();

}

}

}

请参阅See also

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值