我认为我坚持使用 .net 4.0 新安全模型。通常,我只想将 3rd 方程序集加载到沙箱中。听起来很简单,对吧?尽管如此……
我的解决方案中有 2 个项目:CrossAppDomain.exe 和 UntrustedCode.dll。 在 CrossAppdomain 中,我为所有可编码创建了以下基类:
public abstract class Marshallable : MarshalByRefObject, IDisposable
{
[SecurityCritical]
public override object InitializeLifetimeService()
{
return null;
}
public void Dispose()
{
if (!RemotingServices.IsTransparentProxy(this))
{
RemotingServices.Disconnect(this);
}
}
}
并为我将使用的对象创建了基类
public abstract class BaseClass : Marshallable
{
}
在 UntrustedCode.dll 中我创建了派生类
public class UntrustedClass : BaseClass
{
}
要创建 UntrustedClass 的实例,我使用以下工厂:
public sealed class Factory
{
public BaseClass Create(string assName, string typeName)
{
var domain = CreateAppDomain();
ObjectHandle handle;
try
{
// This throws SecurityException with informational message "RequestFailed"
handle = domain.CreateInstance(typeof(AppDomainWorker).Assembly.FullName, typeof(AppDomainWorker).FullName);
}
catch (SecurityException)
{
// While this works fine...
handle = Activator.CreateInstanceFrom(domain,
typeof(AppDomainWorker).Assembly.ManifestModule.FullyQualifiedName,
typeof(AppDomainWorker).FullName);
}
var worker = (AppDomainWorker)handle.Unwrap();
worker.LoadAssemblies();
var obj = worker.Create(assName, typeName);
worker.Dispose();
return obj;
}
private AppDomain CreateAppDomain()
{
var name = Guid.NewGuid().ToString();
var permissions = new PermissionSet(PermissionState.None);
permissions.AddPermission(new SecurityPermission(PermissionState.Unrestricted));
permissions.AddPermission(new ReflectionPermission(PermissionState.Unrestricted));
permissions.AddPermission(new FileIOPermission(PermissionState.Unrestricted));
var appSetup = new AppDomainSetup
{
ApplicationName = name,
ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
ShadowCopyDirectories = Path.GetFullPath(@"..\..\..\UntrustedCode\bin"),
ShadowCopyFiles = "true"
};
// Since Marshallable.InitializeLifetimeServices is overriden and marked with [SecurityCritical]
// we should add this assembly in full trusted list.
// Otherwise. TypeLoadException is thrown with message "Inheritance security rules violated while overriding member:
// 'CrossAppDomains.Marshallable.InitializeLifetimeService()'. Security accessibility of the overriding method must
// match the security accessibility of the method being overriden.
var sn = typeof (AppDomainWorker).Assembly.Evidence.GetHostEvidence<StrongName>();
var domain = AppDomain.CreateDomain(name, null, appSetup, permissions, sn);
return domain;
}
private sealed class AppDomainWorker : Marshallable
{
public BaseClass Create(string assName, string typeName)
{
var assembly = AppDomain.CurrentDomain.GetAssemblies()
.Single(a => assName.StartsWith(a.GetName().Name));
// Here TypeLoadException is thrown: Inheritance security rules violated by type: 'UntrustedCode.UntrustedClass'.
// Derived types must either match the security accessibility of the base type or be less accessible.
var obj = (BaseClass)Activator.CreateInstanceFrom(assembly.Location, typeName).Unwrap();
Debug.Assert(!RemotingServices.IsTransparentProxy(obj));
return obj;
}
public void LoadAssemblies()
{
var assemblyName = AssemblyName.GetAssemblyName(Path.GetFullPath(@"..\..\..\UntrustedCode\bin\Debug\UntrustedCode.dll"));
Assembly.Load(assemblyName);
}
}
}
问题来了:
在 Factory.Create() 中,我仅在使用 Activator.CreateInstance 时才成功创建 AppDomainWorker 类。而更直接的 AppDomain.CreateInstanceAndUnwrap 失败了。这看起来很不稳定,我的意思是这是错误或安全漏洞。但是没关系,解决方法有效
在 AppDomainWorker.Create() 中我得到 TypeLoadException:类型违反了继承安全规则:'UntrustedCode.UntrustedClass'。派生类型必须与基类型的安全可访问性相匹配或更难访问。我不知道如何解决它。这是我的问题
附言我知道 [assembly: SecurityRules(SecurityRuleSet.Level1)] ,但我想知道如何让事情在 .net 4.0 安全模型中工作
编辑: 添加 [assembly: AllowPartialTrustCallers] 后,我遇到了一大堆新问题:我需要用 [SecuritySafeCritical] 明确标记所有使用 LogManager.GetCurrentClassLogger() 创建 nlog loggger 的代码,然后是所有使用带有记录器的初始化字段的代码。这是 Not Acceptable 。那么也许还有其他解决方法?
最佳答案
我认为,我只需将 UntrustedClass 使用的类和使用安全关键代码的代码移动到单独的程序集中。
即将 BaseClass、Marshallable、Factory 移动到某些 Api.dll 中。然后用 [APTCA] 标记程序集并用 [SecuritySafe] 修饰必要的方法。那么任何现有代码都应该可以正常工作,因为 [APTCA] 仅适用于 Api.dll。
此方法适用于示例项目,但我不能确定它是否适合我当前的项目。我会在实现后立即通知您。
关于c# - .net 4.0 安全模型。另一个 "Inheritance security rules violated by type..."异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21550175/