反射的安全注意事项Security Considerations for Reflection

通过反射能够获取有关类型和成员的信息,并能访问成员(即,调用方法和构造函数来获取和设置属性值,添加和移除事件处理程序,等等)。Reflection provides the ability to obtain information about types and members, and to access members (that is, to call methods and constructors, to get and set property values, to add and remove event handlers, and so on). 使用反射可以获取有关类型的信息并且成员是不受限制的。The use of reflection to obtain information about types and members is not restricted. 所有代码都可使用反射来执行以下任务:All code can use reflection to perform the following tasks:

  • 枚举类型和成员,并检查其元数据。Enumerate types and members, and examine their metadata.

  • 枚举并检查程序集和模块。Enumerate and examine assemblies and modules.

与之相反,使用反射来访问成员会受到限制。Using reflection to access members, by contrast, is subject to restrictions. 从 .NET Framework 4 开始,只有受信任的代码才能使用反射来访问安全关键成员。Beginning with the .NET Framework 4, only trusted code can use reflection to access security-critical members. 而且,只有受信任的代码才能使用反射访问无法由已编译代码直接访问的非公共成员。Furthermore, only trusted code can use reflection to access nonpublic members that would not be directly accessible to compiled code. 最后,使用反射访问关键安全成员的代码必须具有关键安全成员要求的任何权限,就像编译的代码一样。Finally, code that uses reflection to access a safe-critical member must have whatever permissions the safe-critical member demands, just as with compiled code.

具有一定的权限,代码可以使用反射来执行以下类型的访问:Subject to necessary permissions, code can use reflection to perform the following kinds of access:

  • 访问不是安全关键的公共成员。Access public members that are not security-critical.

  • 若这些成员不是安全关键,则访问可进入编译代码的非公共成员。Access nonpublic members that would be accessible to compiled code, if those members are not security-critical. 此类非公共成员的示例包括:Examples of such nonpublic members include:

    • 调用代码的基础类的受保护成员。Protected members of the calling code's base classes. (在反射中,这称为系列级访问权限。)(In reflection, this is referred to as family-level access.)

    • 调用代码的程序集中的 internal 成员(Visual Basic 中的 Friend 成员)。internal members (Friend members in Visual Basic) in the calling code's assembly. (在反射中,这称为程序集级别的访问。)(In reflection, this is referred to as assembly-level access.)

    • 包含调用代码的类的其他实例的私有成员。Private members of other instances of the class that contains the calling code.

例如,在沙盒应用程序域中运行的代码被限制于此列表所述的访问权限,除非该应用程序域授予其他权限。For example, code that is run in a sandboxed application domain is limited to the access described in this list, unless the application domain grants additional permissions.

从 .NET Framework 2.0 Service Pack 1 开始,尝试访问通常无法访问的成员将生成目标对象授权集的需求以及带 ReflectionPermissionFlag.MemberAccess 标志的 ReflectionPermissionStarting with the .NET Framework 2.0 Service Pack 1, attempting to access members that are normally inaccessible generates a demand for the grant set of the target object plus ReflectionPermission with the ReflectionPermissionFlag.MemberAccess flag. 以“完全信任”运行的代码(比如,从命令行启动的应用程序中的代码)始终可以满足这些权限。Code that is running with full trust (for example, code in an application that is launched from the command line) can always satisfy these permissions. (如本文后续部分所述,访问安全关键成员时会受到限制。)(This is subject to limitations in accessing security-critical members, as described later in this article.)

沙盒应用程序域可以向 ReflectionPermission 授予 ReflectionPermissionFlag.MemberAccess 标志,如本文后续部分中的访问通常不可访问的成员中所述。Optionally, a sandboxed application domain can grant ReflectionPermission with the ReflectionPermissionFlag.MemberAccess flag, as described in the section Accessing Members That Are Normally Inaccessible, later in this article.

访问安全关键成员Accessing Security-Critical Members

一个成员如果具有 SecurityCriticalAttribute,而它属于具有 SecurityCriticalAttribute 的类型,或是它在安全关键程序集中,则该成员为安全关键成员。A member is security-critical if it has the SecurityCriticalAttribute, if it belongs to a type that has the SecurityCriticalAttribute, or if it is in a security-critical assembly. 从 .NET Framework 4 开始,访问安全关键成员的规则如下:Beginning with the .NET Framework 4, the rules for accessing security-critical members are as follows:

无论是通过已编译代码直接访问还是使用反射访问安全关键成员,这些规则都不会变。These rules are the same whether a security-critical member is accessed directly by compiled code, or accessed by using reflection.

从命令行运行的应用程序代码将以“完全信任”运行。Application code that is run from the command line runs with full trust. 只要不被标记为透明,它就可以使用反射来访问安全关键成员。As long as it is not marked as transparent, it can use reflection to access security-critical members. 当以“部分信任”(例如,在沙盒应用程序域中)运行相同的代码时,程序集的信任级别将确定它是否可以访问安全关键代码:如果该程序集具有强名称,并且安装在全局程序集缓存中,它则是受信任的程序集,可以调用安全关键成员。When the same code is run with partial trust (for example, in a sandboxed application domain) the assembly's trust level determines whether it can access security-critical code: If the assembly has a strong name and is installed in the global assembly cache, it is a trusted assembly and can call security-critical members. 如果不是受信任的,即使未标记为透明,它也将变为透明,并且它不能访问安全关键成员。If it is not trusted, it becomes transparent even though it was not marked as transparent, and it cannot access security-critical members.

有关 .NET Framework 4 中安全模型的详细信息,请参阅安全更改For more information about the security model in the .NET Framework 4, see Security Changes.

反射和透明度Reflection and Transparency

以 .NET Framework 4 开始,公共语言运行时从若干方面确定一个类型或成员的透明度级别,包括程序集和应用程序域的信任级别。Beginning with the .NET Framework 4, the common language runtime determines the transparency level of a type or member from several factors, including the trust level of the assembly and the trust level of the application domain. 反射提供了 IsSecurityCriticalIsSecuritySafeCriticalIsSecurityTransparent 属性,以使你能够发现类型的透明度级别。Reflection provides the IsSecurityCritical, IsSecuritySafeCritical, and IsSecurityTransparent properties to enable you to discover the transparency level of a type. 下表显示了这些属性的有效组合。The following table shows the valid combinations of these properties.

安全级别Security level IsSecurityCriticalIsSecurityCritical IsSecurityCriticalIsSecuritySafeCritical IsSecurityTransparentIsSecurityTransparent
严重Critical true false false
安全-关键Safe-critical true true false
透明Transparent false false true

使用这些属性比检查程序集及其类型的安全批注、检查当前的信任级别,以及尝试复制运行时的规则要简单得多。Using these properties is much simpler than examining the security annotations of an assembly and its types, checking the current trust level, and attempting to duplicate the runtime's rules. 例如,当从命令行中运行时,相同的类型可以是安全关键,或者在沙盒应用程序域中运行时,它们又是安全-透明的。For example, the same type can be security-critical when it is run from the command line, or security-transparent when it is run in a sandboxed application domain.

MethodBaseFieldInfoTypeBuilderMethodBuilderDynamicMethod 上有类似的属性。There are similar properties on the MethodBase, FieldInfo, TypeBuilder, MethodBuilder, and DynamicMethod classes. (对于其他反射和反射发出抽象化,安全属性应用到关联的方法;例如,在它们应用于属性访问器的属性的情况下)。(For other reflection and reflection emit abstractions, security attributes are applied to the associated methods; for example, in the case of properties they are applied to the property accessors.)

访问通常不可访问的成员Accessing Members That Are Normally Inaccessible

根据公共语言运行时的可访问性规则,若要使用反射来调用无法访问的成员,你的代码必须获得以下两个权限之一:To use reflection to invoke members that are inaccessible according to the accessibility rules of the common language runtime, your code must be granted one of two permissions:

例如,假设你为应用程序域授予 Internet 权限以及带 ReflectionPermissionFlag.RestrictedMemberAccess 标志的 ReflectionPermission,则使用两个程序集 A 和 B 运行 Internet 应用程序。For example, suppose you grant an application domain Internet permissions plus ReflectionPermission with the ReflectionPermissionFlag.RestrictedMemberAccess flag, and then run an Internet application with two assemblies, A and B.

  • 程序集 A 可以使用反射来访问程序集 B 的私有成员,因为程序集 B 的授予集不包括一个 A 尚未被授予的任何权限。Assembly A can use reflection to access private members of assembly B, because the grant set of assembly B does not include any permissions that A has not been granted.

  • 程序集 A 不能使用反射来访问 .NET Framework 程序集的私有成员(如 mscorlib.dll),因为 mscorlib.dll 是完全受信任的,因此有尚未被授予给程序集 A 的权限。代码访问安全性在运行时审核堆栈将引发 MemberAccessExceptionAssembly A cannot use reflection to access private members of .NET Framework assemblies such as mscorlib.dll, because mscorlib.dll is fully trusted and therefore has permissions that have not been granted to assembly A. A MemberAccessException is thrown when code access security walks the stack at run time.

序列化Serialization

对于序列化,带 SecurityPermissionAttribute.SerializationFormatter 标志的 SecurityPermission,无论其访问级别是什么,都能够获取和设置序列化类型的成员。For serialization, SecurityPermission with the SecurityPermissionAttribute.SerializationFormatter flag provides the ability to get and set members of serializable types, regardless of accessibility. 此权限使代码可以发现并更改实例的私有状态。This permission enables code to discover and change the private state of an instance. (除被授予适当权限以外,在元数据中该类型必须标记为可序列化。)(In addition to being granted the appropriate permissions, the type must be marked as serializable in metadata.)

类型 MethodInfo 的参数Parameters of Type MethodInfo

尤其是对受信任的代码,要避免编写采用 MethodInfo 参数的公共成员。Avoid writing public members that take MethodInfo parameters, especially for trusted code. 此类成员可能更容易受到恶意代码的攻击。Such members might be more vulnerable to malicious code. 例如,考虑采用 MethodInfo 参数的高度受信任代码中的公共成员。For example, consider a public member in highly trusted code that takes a MethodInfo parameter. 假定公共成员间接调用所提供参数 Invoke 上的方法。Assume that the public member indirectly calls the Invoke method on the supplied parameter. 如果公共成员不执行必要的权限检查,对 Invoke 方法的调用会一直成功,因为安全系统确定了该调用方为高度受信任的调用方。If the public member does not perform the necessary permission checks, the call to the Invoke method will always succeed, because the security system determines that the caller is highly trusted. 即使恶意代码没有直接调用该方法的权限,它仍可以通过调用公共成员间接调用该方法。Even if malicious code does not have the permission to directly invoke the method, it can still do so indirectly by calling the public member.

版本信息Version Information

请参阅See also