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




.net-4.0 code-access-security (2)

我有一个[AllowPartiallyTrustedCallers]类库包含System.DataAnnotations.ValidationAttribute的子类型。 该库用于WCF服务的合同类型。

在.NET 2 / 3.5,这工作得很好。 但是,从.NET 4.0开始,在Visual Studio调试器中运行服务的客户端会导致出现异常“ 继承安全规则违反了类型:'(我的ValidationAttribute的子类型)'派生类型必须匹配基类型或不易访问 “(System.TypeLoadException)

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

  1. ValidationAttribute的子类位于AllowPartiallyTrustedCallers程序集中
  2. 反射用于检查属性
  3. 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,你会得到异常!

按Ctrl-F5(开始不调试),它都可以毫无例外地正常工作...

奇怪的是,根据你运行程序的方式(F5或Ctrl + F5),ValidationAttribute将会或不会是安全关键的。 如上面代码中的Console.WriteLine所示。 但是,再次,这似乎也发生与其他属性(和类型?)。

现在的问题...

为什么从ValidationAttribute继承时有这种行为,但从System.Attribute继承时没有? (使用Reflector我没有找到ValidationAttribute类或它的程序集上的特殊设置)

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

非常感谢! 鲁迪


为什么从ValidationAttribute继承时有这种行为,但从System.Attribute继承时没有? (使用Reflector我没有找到ValidationAttribute类或它的程序集上的特殊设置)

这是因为System.ComponentModel.DataAnnotations程序集是有条件的APTCA,即它被标记为以下属性。

[assembly: AllowPartiallyTrustedCallers(PartialTrustVisibilityLevel = PartialTrustVisibilityLevel.NotVisibleByDefault)]

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

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

这似乎是VS主机的一个错误,这对您的情况是不幸的。 另一方面,你应该确定你想要你的程序集是APTCA。 如果有必要,那么你有几个选项。

  • 你可以保留你的程序集。 这是有利的,因为在最典型的部分信任环境ASP.NET中,DataAnnotations程序集将始终被认为是APTCA。 当然,你在VS托管过程中失去了使用调试器的能力。
  • 您也可以标记您的组件C-APTCA。 您将能够在VS托管过程中使用调试器,但是您在ASP.NET中的程序集的用户将需要将您的程序集添加到web.config中的<partialTrustVisibleAssemblies>元素,以使其成为APTCA。
  • 你可以使你的属性SecurityCritical,所以你将能够使用调试器,并不需要在ASP.NET中的任何特殊配置,但所有使用你的属性的类也必须是关键的。

出于某种原因,网站将文字发布到与我写作时页面上完全不同的问题上,这很奇怪。