背景:Noda Time包含许多
我们最近收到了issue report件野田的 时间2.x failing within .NET Fiddle.使用Noda的相同代码 Time 1.x工作正常.抛出的异常如下:
覆盖成员时违反继承安全规则: ‘NodaTime.Duration.System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)‘.安全性 重写方法的可访问性必须与安全性匹配 被重写的方法的可访问性.
我已经把范围缩小到目标框架:1.十、
我已经设法在当地的一个项目中重现了这一点,但我还没有
在VS2017中复制的步骤:
- 创建新的解决方案
- 创建一个新的classic Windows控制台应用程序.网
- 在"项目属性"中,转到"签名"并使用对程序集进行签名
- 粘贴以下代码以替换
Program.cs
.这是一个 this Microsoft sample中代码的缩写版本. 我把所有的路都保持不变,所以如果你想回到 Fuller代码,您应该不需要更改任何其他内容.
代码:
using System;
using System.Security;
using System.Security.Permissions;
class Sandboxer : MarshalByRefObject
{
static void Main()
{
var adSetup = new AppDomainSetup();
adSetup.ApplicationBase = System.IO.Path.GetFullPath(@"..\..\..\UntrustedCode\bin\Debug");
var permSet = new PermissionSet(PermissionState.None);
permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
var fullTrustAssembly = typeof(Sandboxer).Assembly.Evidence.GetHostEvidence<System.Security.Policy.StrongName>();
var newDomain = AppDomain.CreateDomain("Sandbox", null, adSetup, permSet, fullTrustAssembly);
var handle = Activator.CreateInstanceFrom(
newDomain, typeof(Sandboxer).Assembly.ManifestModule.FullyQualifiedName,
typeof(Sandboxer).FullName
);
Sandboxer newDomainInstance = (Sandboxer) handle.Unwrap();
newDomainInstance.ExecuteUntrustedCode("UntrustedCode", "UntrustedCode.UntrustedClass", "IsFibonacci", new object[] { 45 });
}
public void ExecuteUntrustedCode(string assemblyName, string typeName, string entryPoint, Object[] parameters)
{
var target = System.Reflection.Assembly.Load(assemblyName).GetType(typeName).GetMethod(entryPoint);
target.Invoke(null, parameters);
}
}
- 创建另一个名为"不可信代码"的项目.这应该是一个
- 在集会上签名;您可以使用一个新密钥,也可以使用与的相同密钥
- 将以下代码粘贴到
Class1.cs
中(覆盖那里的内容):
代码:
using System;
using System.Runtime.Serialization;
using System.Security;
using System.Security.Permissions;
// [assembly: AllowPartiallyTrustedCallers]
namespace UntrustedCode
{
public class UntrustedClass
{
// Method named oddly (given the content) in order to allow MSDN
// sample to run unchanged.
public static bool IsFibonacci(int number)
{
Console.WriteLine(new CustomStruct());
return true;
}
}
[Serializable]
public struct CustomStruct : ISerializable
{
private CustomStruct(SerializationInfo info, StreamingContext context) { }
//[SecuritySafeCritical]
//[SecurityCritical]
//[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
throw new NotImplementedException();
}
}
}
运行CodeRunner项目会出现以下异常(重新格式化以提高可读性):
未处理的异常:System.Reflection.TargetInvocationException:
调用目标引发异常.
->;
System.TypeLoadException:
覆盖成员时违反继承安全规则:
‘UntrustedCode.CustomStruct.System.Runtime.Serialization.ISerializable.GetObjectData(.).
重写方法的安全可访问性必须与安全性匹配
被重写的方法的可访问性.
注释掉的属性显示了我try 过的东西:
-
SecurityPermission
由两篇不同的MS文章(first, second),尽管 有趣的是,它们围绕显式/隐式接口实现做不同的事情 -
SecurityCritical
是野田佳彦目前拥有的,也是this question's answer的建议 - 代码分析规则消息有点建议使用
SecuritySafeCritical
- 如果没有any个属性,代码分析规则是满意的——有
SecurityPermission
个或SecurityCritical
个 - 野田佳彦的时间有
AllowPartiallyTrustedCallers
个;这里的示例在应用或不应用属性的情况下都不起作用.
如果我向UntrustedCode
程序集添加[assembly: SecurityRules(SecurityRuleSet.Level1)]
(并取消对AllowPartiallyTrustedCallers
属性的注释),代码将毫无例外地运行,但我认为这是一个糟糕的解决方案,可能会妨碍其他代码.
我完全承认,在这种情况下,我很迷茫
(虽然我的目标是.NET 4.5,但我相信是.NET 4.0安全策略的更改导致了这个问题,因此才有了标签.)