【发布时间】:2014-02-28 06:51:40
【问题描述】:
我想我坚持使用 .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 记录器的代码,然后是所有将初始化字段与记录器一起使用的代码。这是不可接受的。那么也许还有其他方法?
【问题讨论】:
-
示例项目链接已过期。
标签: c# .net appdomain code-access-security typeloadexception