我认为我坚持使用.net 4.0新的安全模型。通常,我只想将第三方程序集加载到沙箱中。听起来很简单吧?尽管如此...
我的解决方案中有2个项目:CrossAppDomain.exe和UntrustedCode.dll。 在CrossAppdomain中,我为所有的marshallables创建了以下基类:
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);
}
}
}
这里出现问题:
在AppDomainWorker.Create()中,我收到TypeLoadException :违反了类型的继承安全规则:'UntrustedCode.UntrustedClass'。派生类型必须与基本类型的安全可访问性匹配,或者不太容易访问。我不知道如何解决它。这是我的问题
P.S。我知道[assembly:SecurityRules(SecurityRuleSet.Level1)],但我想知道如何使用.net 4.0安全模型工作
编辑:添加[assembly:AllowPartialTrustCallers]后,我遇到了一大堆新问题:我需要用[SecuritySafeCritical]明确标记使用LogManager.GetCurrentClassLogger()创建nlog loggger的所有代码然后全部使用带有记录器的初始化字段的代码。这是不可接受的。那么也许还有其他办法吗?
答案 0 :(得分:1)
我认为,我只需将UntrustedClass使用的类和使用安全关键代码的代码移动到单独的程序集中。
即。将BaseClass,Marshallable,Factory移动到一些Api.dll中。然后使用[APTCA]标记装配并使用[SecuritySafe]装饰必要的方法。然后任何现有的代码应该没有问题,因为[APTCA]仅适用于Api.dll。
这种方法适用于示例项目,但我无法确定它是否适合我当前的项目。我一实施,就告诉你。