创建不带/空CallContext的AppDomain

时间:2018-08-28 16:01:04

标签: c# appdomain razorengine appdomainsetup callcontext

在ASP.NET应用程序中,我想创建一个AppDomain,在其中将运行不受信任的代码。但是,在初始化和解开程序集加载器时,会引发有关我未传递的类型的异常。它是Web请求(HttpContext.Current.User)中的当前用户,我认为可通过LocalCallContext获得该请求。我不希望当前用户可用于不受信任的代码,实际上,我希望不受信任的代码完全不获取任何上下文。因此,我想我可以传递一个显式的CallContext,但似乎没有这样的事情。我将如何实现?

不受信任的代码是用户提供的Razor模板,将通过RazorEngine执行。

Evidence evidence = new Evidence();
evidence.AddHostEvidence(new Zone(SecurityZone.Internet));
PermissionSet permissionSet = SecurityManager.GetStandardSandbox(evidence);
FileIOPermission permission = new FileIOPermission(PermissionState.None);
FileIOPermissionAccess access = FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery;
permission.AddPathList(access, typeof(AssemblyLoader).Assembly.Location);
permissionSet.AddPermission(permission);

// We have to load ourself with full trust
StrongName loaderAssembly = typeof(AssemblyLoader).Assembly.Evidence.GetHostEvidence<StrongName>();
StrongName razorEngineAssembly = typeof(RazorEngineService).Assembly.Evidence.GetHostEvidence<StrongName>();
StrongName razorAssembly = typeof(RazorTemplateEngine).Assembly.Evidence.GetHostEvidence<StrongName>();
AppDomainSetup appDomainSetup = new AppDomainSetup
{
    ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase
};
AppDomain sandBoxDomain = AppDomain.CreateDomain("Razor Template Sandbox", null, appDomainSetup, permissionSet, loaderAssembly, razorEngineAssembly, razorAssembly);

AssemblyLoader loader = (AssemblyLoader)sandBoxDomain.CreateInstanceFromAndUnwrap(typeof(AssemblyLoader).Assembly.Location, typeof(AssemblyLoader).FullName);

最后一行抛出此异常,UnrelatedAssembly.SomeType是我的HttpContext.Current.User的类型:

System.Runtime.Serialization.SerializationException: 'Type is not resolved for member 'UnrelatedAssembly.SomeType,UnrelatedAssembly, Version=1.9.0.0, Culture=neutral, PublicKeyToken=null'.'

1 个答案:

答案 0 :(得分:0)

我通过抑制执行上下文的流,并从单独的线程运行目标应用程序域中的所有代码,解决了部分问题。看起来像这样:

var flow = ExecutionContext.SuppressFlow();
try
{
    return Task.Factory.StartNew(() =>
    {
        Thread.CurrentPrincipal = null;
        // setup app domain / run code in other app domain here
        return ....;
    }).Result;
}
finally
{
    flow.Undo();
}