背景: 野田时光包含许多
serializable structs. While I dislike binary serialization, we
回到1.x 时间线,收到了许多支持它的请求。
我们通过实现 ISerializable
接口来支持它。
我们最近收到了一个问题 野田佳彦的报告 时间2.x < a href = “ https://dotnetfiddle.NET/vTCzMJ”rel = “ noReferrer”> 在.NET 中失败 Fiddle . 使用 Noda 的相同代码 Time 1.x 运行良好,抛出的异常如下:
重写成员时违反了继承安全规则: ‘ NodaTime.Duration.System.Runtime.Serialization.ISerialization.GetObjectData (System.Runtime.Serialization. SerializationInfo, System.Runtime.Serialization. StreamingContext)’。安全性 重写方法的可访问性必须与安全性匹配 被重写方法的可访问性。
我已经把范围缩小到目标框架: 1.x 目标.NET 3.5(客户端配置文件) ; 2.x 目标.NET 4.5 在支持 PCL 和.NET 核心以及 项目文件结构,但看起来这是无关紧要的。
我设法在当地的一个项目中复制了这个,但是我没有 找到了解决办法。
Steps to reproduce in VS2017:
Program.cs
在 < a href = “ https://Learn.Microsoft.com/en-us/dotnet/Framework/misc/how-to-run-part-trust-code-in-a-sandbox # example”rel = “ norefrer”> this Microsoft
样本 。
I've kept all the paths the same, so if you want to go back to the
更完整的代码,您不应该需要更改任何其他代码。Code:
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 项目会出现以下异常(为了便于阅读而重新格式化) :
未处理的异常: 系统、反射、 TargetInvocationException:
Exception has been thrown by the target of an invocation.
-
System.TypeLoadException:
重写成员时违反了继承安全规则:
'UntrustedCode.CustomStruct.System.Runtime.Serialization.ISerializable.GetObjectData(...).
重写方法的安全可访问性必须与安全性匹配
被重写方法的可访问性。
注释掉的属性显示了我试过的东西:
SecurityCritical
is what Noda Time currently has, and is what 这个问题的答案 suggestsSecuritySafeCritical
SecurityPermission
或 SecurityCritical
目前,规则告诉您删除属性-除非您 做有 AllowPartiallyTrustedCallers
。无论在哪种情况下,遵循建议都没有帮助。AllowPartiallyTrustedCallers
; 这里的示例既不能使用应用的属性,也不能使用不应用的属性。如果我将 [assembly: SecurityRules(SecurityRuleSet.Level1)]
添加到 UntrustedCode
程序集(并取消对 AllowPartiallyTrustedCallers
属性的注释) ,代码将无一例外地运行,但我认为这是一个糟糕的解决方案,可能会妨碍其他代码。
我完全承认在这种事情上我很迷茫
所以我对目标.NET 4.5和
但是允许我的类型实现 ISerializable
,并且仍然在
像.NET Fiddle 这样的环境?
(While I'm targeting .NET 4.5, I believe it's the .NET 4.0 security policy changes that caused the issue, hence the tag.)