C# 如何在具有AllowPartiallyTrustedCallersAttribute的库程序集中实现.NET 4中的Exception.GetObjectData?

C# 如何在具有AllowPartiallyTrustedCallersAttribute的库程序集中实现.NET 4中的Exception.GetObjectData?,c#,code-access-security,C#,Code Access Security,我有一个标有AllowPartiallyTrustedCallersAttribute的程序集,其中包含一个自定义异常类。我想通过重写GetObjectData使其可序列化 在.NET4中,GetObjectData已成为一种SecurityCritical方法。这意味着重写也需要是SecurityCritical。由于我的程序集是用AllowPartiallyTrustedCallersAttribute标记的,所以除非另有规定,否则其中的所有代码都是自动SecurityTransparent

我有一个标有
AllowPartiallyTrustedCallersAttribute
的程序集,其中包含一个自定义异常类。我想通过重写
GetObjectData
使其可序列化

在.NET4中,
GetObjectData
已成为一种
SecurityCritical
方法。这意味着重写也需要是
SecurityCritical
。由于我的程序集是用
AllowPartiallyTrustedCallersAttribute
标记的,所以除非另有规定,否则其中的所有代码都是自动
SecurityTransparent
。因此,我将
SecurityCriticalAttribute
应用于GetObjectData覆盖:

using System;
using System.Runtime.Serialization;
using System.Security;

[assembly:AllowPartiallyTrustedCallers]

namespace Library
{
  [Serializable]
  public class MyException : Exception
  {
    public string String;

    public MyException ()
    {
    }

    protected MyException (SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
      String = info.GetString ("String");
    }

    [SecurityCritical]
    public override void GetObjectData (System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
    {
      info.AddValue ("String", String);
      base.GetObjectData (info, context);
    }
  }
}
这在完全信任的情况下可以很好地工作,例如,当我从桌面运行链接此程序集的代码时

然而,当我从安全沙箱(见下文)使用此类时,我得到一个
TypeLoadException

重写成员时违反了继承安全规则: 'Library.MyException.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext')。安全 重写方法的可访问性必须与安全性匹配 正在重写的方法的可访问性

我的问题是:

  • 为什么我会得到这个例外?我确实将覆盖标记为
    SecurityCritical
    ,那么问题出在哪里
  • 由于在我的沙盒中忽略了
    SecurityCriticalAttribute
    ,因此该类在其他部分信任主机(如IIS/ASP.NET或SQL Server)中的行为如何
  • 如何在.NET4中实现可序列化的异常类
沙箱代码:

var evidence = new Evidence();
evidence.AddHostEvidence (new Zone (SecurityZone.Internet));
var setupInfo = AppDomain.CurrentDomain.SetupInformation;
var permissionSet = SecurityManager.GetStandardSandbox (evidence);
permissionSet.AddPermission (new ReflectionPermission (ReflectionPermissionFlag.MemberAccess));
permissionSet.AddPermission (new SecurityPermission (SecurityPermissionFlag.ControlEvidence));
var sandbox = AppDomain.CreateDomain ("Sandbox", evidence, setupInfo, permissionSet);

除了完全受信任的代码外,您不能调用标记为的代码:

SecurityCriticalAttribute相当于完整配置的链接需求 信任。使用SecurityCriticalAttribute标记的类型或成员可以 只能由完全受信任的代码调用;它不必要求 特定权限。部分受信任的代码无法调用它


有一个相关的问题正在讨论的使用。

好吧,我知道这篇文章已经过时了,但是根据我最近的观察,如果您不让程序集完全信任沙盒
AppDomain
,加载的程序集中的所有代码都将是透明的。这意味着应用于MyException.GetObjectData的
SecurityCriticalAttribute
将不起任何作用。它将是SeurityTransparent的,并且肯定不会与其安全关键的基本方法兼容

希望这个提示能有所帮助


有关如何将沙盒
AppDomain
中的某些程序集标记为FullyTrust的信息,请参阅。

您自己已经回答了问题的第一部分。您的程序集正在以安全透明的方式加载,因为它没有以完全信任的方式加载,因此忽略了
SecurityCritical
属性。所以你得到了一个例外


您不应该重写
GetObjectData
,而应该处理事件并创建一个实现的类型来存储异常状态以进行序列化。实际上,我不调用SecurityCritical成员(
GetObjectData
),我只想在不违反“继承安全规则”的情况下覆盖它。这在部分受信任的程序集中是不可能的吗?我不这样认为,因为您的重写仍然用该属性标记。不过,看起来securitysafecritical属性可以满足您的需要。它会将您的覆盖标记为安全关键型,并可通过透明代码安全访问。通过上面的链接:“部分受信任的类型和成员可以访问标记有SecuritySafeCriticalAttribute属性的类型或成员。”否,
SecuritySafeCritical
不能用于重写
SecurityCritical
方法。(我试过了;使用
SecuritySafeCritical
我得到了“继承安全规则”例外,即使是完全信任的情况。)