2011-11-22 72 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