2011-11-22 53 views
5

我试图使用C#作为脚本语言,使用CSharpCodeProvider(使用VS2010和.NET 4.0)。我希望脚本以最小权限在受限制的AppDomain中运行。目前,我在尝试实例化AppDomain中的类时遇到异常(调用CreateInstanceAndUnwrap())。这里是再现异常一些简化的代码:Sandboxed AppDomain中的SecurityException

using System; 
using System.Collections.Generic; 
using Microsoft.CSharp; 
using System.CodeDom; 
using System.CodeDom.Compiler; 
using System.Security; 
using System.Security.Policy; 
using System.Security.Permissions; 
using System.Reflection; 
using System.Runtime.Remoting; 

namespace ConsoleApp 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      // set permissions 
      PermissionSet permissions = new PermissionSet(PermissionState.None); 
      permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); 

      AppDomainSetup adSetup = new AppDomainSetup(); 
      adSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; 

      //Create a list of fully trusted assemblies 
      Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies(); 
      List<StrongName> sns = new List<StrongName>(); 
      for (int x = 0; x < asms.Length; x++) 
      { 
       StrongName sn = asms[x].Evidence.GetHostEvidence<StrongName>(); 
       if (sn != null && sns.Contains(sn) == false) 
        sns.Add(sn); 
      } 
      //this includes: "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"    

      AppDomain domain = AppDomain.CreateDomain("NewAppDomain", AppDomain.CurrentDomain.Evidence, adSetup, permissions);//, sns);//, sn4, sn, sn2, sn3); 
      try 
      { 
       String asmName = Assembly.GetExecutingAssembly().FullName; 
       String typeName = typeof(ConsoleApp.ScriptRunner).FullName; 
       //Throws exception here 
       ScriptRunner scriptRunner = domain.CreateInstanceAndUnwrap(asmName, typeName) as ScriptRunner; 
      } 
      catch (SecurityException se) 
      { 
       System.Diagnostics.Debug.WriteLine(se.Message); 
      } 
      catch (Exception ex) 
      { 
       System.Diagnostics.Debug.WriteLine(ex.Message); 
      } 
     } 
    } 

    public class ScriptRunner : MarshalByRefObject 
    {  
     public ScriptRunner() 
     { 
      //A breakpoint placed here is never reached. 
      CompilerParameters param; 
      param = new CompilerParameters(); 
      param.CompilerOptions = ""; 
      param.GenerateExecutable = false; 
      param.GenerateInMemory = true; 
      param.IncludeDebugInformation = false; 

      // C# compiler 
      CSharpCodeProvider codeProvider = new CSharpCodeProvider(); 

      CompilerResults results = codeProvider.CompileAssemblyFromFile(param, "Danger.cs");   
     } 
    } 
} 

异常正在从mscorlib程序抛出并且它是一个System.Reflection.TargetInvocationException具有内System.Security.SecurityException。这里是个例外:

System.Reflection.TargetInvocationException was unhandled 
    Message=Exception has been thrown by the target of an invocation. 
    Source=mscorlib 
    StackTrace: 
     at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) 
     at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) 
     at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) 
     at System.Activator.CreateInstance(Type type, Boolean nonPublic) 
     at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) 
     at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) 
     at System.Activator.CreateInstance(String assemblyName, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence securityInfo, StackCrawlMark& stackMark) 
     at System.Activator.CreateInstance(String assemblyName, String typeName) 
     at System.AppDomain.CreateInstance(String assemblyName, String typeName) 
     at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName) 
     at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName) 
     at ConsoleApp.Program.Main(String[] args) in C:\Documents and Settings\NaultyCS\my documents\visual studio 2010\Projects\ConsoleApplication4\ConsoleApplication4\Program.cs:line 46 
     at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
     at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
     at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
     at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
     at System.Threading.ThreadHelper.ThreadStart() 
    InnerException: System.Security.SecurityException 
     Message=Request failed. 
     Source=ConsoleApplication4 
     GrantedSet=<PermissionSet class="System.Security.PermissionSet" 
version="1"> 
<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
version="1" 
Flags="Execution"/> 
</PermissionSet> 

     PermissionState=<PermissionSet class="System.Security.PermissionSet" 
version="1" 
Unrestricted="true"/> 

     RefusedSet="" 
     Url=file:///C:/Documents and Settings/NaultyCS/my documents/visual studio 2010/Projects/ConsoleApplication4/ConsoleApplication4/bin/Debug/ConsoleApplication4.EXE 
     StackTrace: 
      at ConsoleApp.ScriptRunner..ctor() 
     InnerException: 

所以在我看来,mscorlib是要求完全信任。我已经将它作为完全信任的程序集添加了,但它不起作用。上面的代码工程,如果我设置权限不受限制:

PermissionSet permissions = new PermissionSet(PermissionState.Unrestricted); 

但我想限制AppDomain。我在这里做错了什么?

回答

2

对不起,后期编辑。尝试以下操作。我用一个测试应用程序启动并运行在Visual Studio中。在附注中,我个人不喜欢构造函数中的“逻辑”,因为真正的错误往往会隐藏起来。下面的步骤将Compile逻辑从构造函数移至新方法。

  1. 确保您的控制台应用程序具有StrongName/Signed。
  2. 包含sns变量作为调用AppDomain.CreateDomain的最后一个参数。 LinkDemand权限要求您的ConsoleApp完全受信任。

    AppDomain domain = AppDomain.CreateDomain("NewAppDomain", AppDomain.CurrentDomain.Evidence, adSetup, permissions, sns.ToArray()); 
    
  3. 更改asmName以使用完整文件路径到您的程序集。

    String asmName = Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName; 
    
  4. 删除CreateInstanceAndUnwrap调用以下两行代码

    var handle = Activator.CreateInstanceFrom(domain, asmName, typeName); 
    var scriptRunner = (ScriptRunner)handle.Unwrap(); 
    
  5. 把你所有的代码从构造到一个新的方法,如“开始”。

  6. 添加该行以调用Start方法。

    scriptRunner.Start(); 
    
  7. 添加FileIOPermission以读取您的Danger.cs文件。

    permissions.AddPermission(new FileIOPermission(PermissionState.None) { AllFiles = FileIOPermissionAccess.Read }); 
    
+0

不,如果我设置的PermissionSet到无限制的代码工作正常。我忘了提及,所以我更新了这个问题。问题是安全权限问题。安全异常首先发生在mscorlib中。随着异常上升,它会生成TargetInvocationException。但SecurityException是真正的问题。 – Galen

+0

我根据上述问题和评论的编辑更改了答案。 – Simon

+0

如果我添加上面,我仍然会得到相同的SecurityException。 – Galen