security - 如何从 DataAnnotations.ValidationAttribute 继承(它在 .NET 4 中的 Visual Studio 调试主机下出现 SecureCritical !)

标签 security .net-4.0 code-access-security

我有一个 [AllowPartiallyTrustedCallers] 类库,其中包含 System.DataAnnotations.ValidationAttribute 的子类型。该库用于 WCF 服务的契约(Contract)类型。

在 .NET 2/3.5 中,这运行良好。但是,从 .NET 4.0 开始,在 Visual Studio 调试器中运行该服务的客户端会导致异常“类型违反继承安全规则:'(我的 ValidationAttribute 子类型)'。派生类型必须与基类型的安全可访问性匹配或者不太容易接近。” (System.TypeLoadException)

仅当满足以下所有条件时才会出现该错误:

  • ValidationAttribute 的子类位于 AllowPartiallyTrustedCallers 程序集中
  • 反射用于检查属性
  • 启用 Visual Studio 托管进程(项目属性上的复选框,调试选项卡)

  • 所以基本上,在 Visual Studio.NET 2010 中:
  • 创建一个新的控制台项目,
  • 添加对“System.ComponentModel.DataAnnotations”4.0.0.0 的引用,
  • 编写以下代码:

  • .
    using System;
    
    [assembly: System.Security.AllowPartiallyTrustedCallers()]
    
    namespace TestingVaidationAttributeSecurity
    {
        public class MyValidationAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute
        { }
    
        [MyValidation]
        public class FooBar
        { }
    
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("ValidationAttribute IsCritical: {0}",
                    typeof(System.ComponentModel.DataAnnotations.ValidationAttribute).IsSecurityCritical);
    
                FooBar fb = new FooBar();
                fb.GetType().GetCustomAttributes(true);
    
                Console.WriteLine("Press enter to end.");
                Console.ReadLine();
            }
        }
    }
    
  • 按F5,你会得到异常(exception)!

  • 按 Ctrl-F5(无需调试即可启动),一切正常,无一异常(exception)......

    奇怪的是,根据您运行程序的方式(F5 或 Ctrl+F5),ValidationAttribute 是否是安全关键的。如上面代码中的 Console.WriteLine 所示。但话说回来,这似乎也发生在其他属性(和类型?)上。

    现在问题...

    为什么从 ValidationAttribute 继承时会出现这种行为,而从 System.Attribute 继承时却不会? (使用 Reflector 我没有在 ValidationAttribute 类或其程序集上找到特殊设置)

    我该怎么做才能解决这个问题?如何在 AllowPartiallyTrustedCallers 程序集中保持从 ValidationAttribute 继承的 MyValidationAttribute 而不将其标记为 SecurityCritical,仍然使用新的 .NET 4 级别 2 安全模型,并且仍然使用 VS.NET 调试主机(或其他主机)使其工作?

    非常感谢!
    鲁迪

    最佳答案

    Why do I have this behaviour when inheriting from ValidationAttribute, but not when inheriting from System.Attribute ? (Using Reflector I don't find special settings on the ValidationAttribute class or it's assembly)



    这是因为 System.ComponentModel.DataAnnotations 程序集是有条件的 APTCA,即它标记有以下属性。
    [assembly: AllowPartiallyTrustedCallers(PartialTrustVisibilityLevel = PartialTrustVisibilityLevel.NotVisibleByDefault)]
    

    Visual Studio 启动宿主进程的方式会导致 CLR 不遵守此程序集上的 APTCA,即使默认 AppDomain 是完全受信任的。这意味着 DataAnnotations 程序集中的所有类型和方法都是 SecurityCritical。由于安全透明类型 (MyValidationAttribute) 不能从安全关键类型 (ValidationAttribute) 继承,因此会引发此异常。

    And what can I do to solve this ? How can I keep MyValidationAttribute inheriting from ValidationAttribute in an AllowPartiallyTrustedCallers assembly without marking it SecurityCritical, still using the new .NET 4 level 2 security model and still have it work using the VS.NET debug host (or other hosts) ??



    这似乎是VS主机的一个错误,这对您的情况来说很不幸。另一方面,您真的应该确定您希望您的程序集是 APTCA。如果有必要,那么您有几个选择。
  • 您可以按原样保留程序集。这是有利的,因为在最典型的部分信任环境 ASP.NET 中,DataAnnotations 程序集将始终被视为 APTCA。当然,你失去了在 VS 托管过程中使用调试器的能力。
  • 您也可以标记您的程序集 C-APTCA。您将能够在 VS 托管过程中使用调试器,但是 ASP.NET 中程序集的使用者需要将您的程序集添加到 web.config 中的 元素,以便它成为 APTCA。
  • 您可以将属性设置为 SecurityCritical,这样您就可以使用调试器并且不需要在 ASP.NET 中进行任何特殊配置,但是使用您的属性的所有类也必须是关键的。
  • 关于security - 如何从 DataAnnotations.ValidationAttribute 继承(它在 .NET 4 中的 Visual Studio 调试主机下出现 SecureCritical !),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2690291/

    相关文章:

    firebase - 如何限制每个用户可以上传到 Firebase 存储的存储量?

    c# - 使用 LINQ 读取 XML 文件并使用 IEnumerable 属性创建对象

    winforms - System.TypeLoadException 未处理/覆盖成员时违反了继承安全规则

    .net - 在 .NET 中限制对 DLL 的访问

    c# - 细粒度的权限; PrincipalPermission - 角色与权限分开;

    asp.net - 仅 HTMLEncode 脚本标签

    java - Shiro-Guice 过滤器链角色配置

    windows - Azure 角色本地存储是否保证下一个使用同一主机的应用程序无法访问?

    C# 编译器无法识别正在实现接口(interface)的类

    c# - 检查我的 WPF WebBrowser 中的元素,使用 "inspect element(s)"(IE、Chrome、Firefox)获取 css 路径 ("copy css-path")