2012-12-20 71 views
3

我想將IronPython集成到C#應用程序中用於腳本目的。我還希望腳本在一組安全策略下運行,這些策略限制他們訪問文件系統/網絡/敏感系統資源。研究表明,最流行的方法是使用CAS。這很有效,它不允許用戶使用套接字,訪問文件系統等。但是,當我嘗試爲腳本注入變量以與其交互時,每次訪問某些參數時都會收到安全異常。這隻發生在我在程序集中定義的變量中。如果我使用標準的.NET類型(如Dictionary),它的工作原理很好。IronPython與沙箱CAS

我的代碼:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Reflection; 
using System.Security.Policy; 
using System.Security.Permissions; 
using System.Security; 
using System.IO; 
using Microsoft.Scripting.Hosting; 
using IronPython.Hosting; 
using System.Runtime.Remoting; 
using System.Net; 

namespace python_in_appdomain 
{ 
    [Serializable] 
    public class Whatever 
    { 
     public int i; 
     public Whatever(int i) 
     { 
      this.i = i; 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Remoting(); 
     } 

     public static void Remoting() 
     { 
      AppDomainSetup setup = new AppDomainSetup(); 
      Assembly thisAssembly = Assembly.GetExecutingAssembly(); 
      setup.ApplicationBase = Path.GetDirectoryName(thisAssembly.Location); 

      AssemblyName name = typeof(Program).Assembly.GetName(); 
      StrongName sn = new StrongName(
       new StrongNamePublicKeyBlob(name.GetPublicKey()), 
       name.Name, 
       name.Version 
      ); 

      PermissionSet pset = new PermissionSet(PermissionState.None); 
      pset.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); 
      pset.AddPermission(new ReflectionPermission(PermissionState.Unrestricted)); 

      setup.PartialTrustVisibleAssemblies = new[] { sn.Name + ", PublicKey=" + sn.PublicKey.ToString() }; 
      AppDomain domain = AppDomain.CreateDomain("Sandbox", AppDomain.CurrentDomain.Evidence, setup, pset, sn); 

      String script = @" 
d.Add('hello', 1) 
w.i = 5 
"; 

      Whatever w = new Whatever(4); 
      Dictionary<string, int> d = new Dictionary<string,int>(); 

      ScriptRuntime py = Python.CreateRuntime(domain); 
      ScriptEngine engine = py.GetEngine("py"); 
      ScriptScope scope = engine.CreateScope(); 
      scope.SetVariable("w", w); 
      scope.SetVariable("d", d); 

      int result; 
      Console.WriteLine(w.i); 
      d.TryGetValue("hello", out result); 
      Console.WriteLine(result); 
      Console.WriteLine("-----"); 

      try 
      { 
       engine.Execute(script, scope); 
      } 
      catch (Exception exc) 
      { 
       Console.WriteLine(exc.ToString()); 
      } 

      w = scope.GetVariable<Whatever>("w"); 
      d = scope.GetVariable<Dictionary<string,int>>("d"); 

      Console.WriteLine("-----"); 
      Console.WriteLine(w.i); 
      d.TryGetValue("hello", out result); 
      Console.WriteLine(result); 

     } 
    } 
} 

談到了「w.i = 5」上線55導致程序下受限制的安全設置正常執行。在第47行將PermissionState設置爲Unrestricted允許腳本的兩行正常執行。以下是我收到的錯誤消息:

System.Security.SecurityException: Request failed. 
    at System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(IRuntimeMethodInfo method) 
    at System.Reflection.Emit.DynamicMethod.CreateDelegate(Type delegateType, Object target) 
    at System.Dynamic.Utils.TypeExtensions.CreateDelegate(MethodInfo methodInfo, Type delegateType, Object target) 
    at System.Linq.Expressions.Compiler.LambdaCompiler.CreateDelegate() 
    at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator) 
    at System.Linq.Expressions.Expression`1.Compile() 
    at System.Runtime.CompilerServices.CallSiteBinder.BindCore[T](CallSite`1 site, Object[] args) 
    at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1) 
    at Microsoft.Scripting.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame) 
    at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame) 
    at Microsoft.Scripting.Interpreter.LightLambda.Run2[T0,T1,TRet](T0 arg0, T1 arg1) 
    at IronPython.Compiler.PythonScriptCode.RunWorker(CodeContext ctx) 
    at IronPython.Compiler.PythonScriptCode.Run(Scope scope) 
    at IronPython.Compiler.RuntimeScriptCode.InvokeTarget(Scope scope) 
    at IronPython.Compiler.RuntimeScriptCode.Run(Scope scope) 
    at Microsoft.Scripting.SourceUnit.Execute(Scope scope, ErrorSink errorSink) 
    at Microsoft.Scripting.Hosting.ScriptSource.Execute(ScriptScope scope) 
    at Microsoft.Scripting.Hosting.ScriptEngine.Execute(String expression, ScriptScope scope) 
    at Microsoft.Scripting.Hosting.ScriptEngine.Execute(String expression, ScriptScope scope) 
    at python_in_appdomain.Program.Remoting() in C:\Users\dave\Documents\Visual Studio 2010\Projects\IronPythonTest\IronPythonTest\Program.cs:line 7 
6 
The action that failed was: 
Demand 
The type of the first permission that failed was: 
System.Security.PermissionSet 
The demand was for: 
<PermissionSet class="System.Security.PermissionSet" 
version="1" 
Unrestricted="true"/> 

The granted set of the failing assembly was: 
<PermissionSet class="System.Security.PermissionSet" 
version="1"> 
<IPermission class="System.Security.Permissions.ReflectionPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
version="1" 
Unrestricted="true"/> 
<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
version="1" 
Flags="Execution"/> 
</PermissionSet> 

The assembly or AppDomain that failed was: 
Microsoft.Dynamic, Version=1.1.0.20, Culture=neutral, PublicKeyToken=7f709c5b713576e1 
The method that caused the failure was: 
Int32 Run(Microsoft.Scripting.Interpreter.InterpretedFrame) 
The Zone of the assembly that failed was: 
Internet 
The Url of the assembly that failed was: 
file:///C:/Users/dave/Documents/Visual Studio 2010/Projects/IronPythonTest/IronPythonTest/bin/Debug/Microsoft.Dynamic.DLL 

Unhandled Exception: System.Security.SecurityException: Request failed. 
    at System.Delegate.BindToMethodInfo(Object target, IRuntimeMethodInfo method, RuntimeType methodType, DelegateBindingFlags flags) 
    at System.Delegate.CreateDelegate(Type type, MethodInfo method, Boolean throwOnBindFailure) 
    at System.Dynamic.Utils.TypeExtensions.CreateDelegate(MethodInfo methodInfo, Type delegateType) 
    at System.Runtime.CompilerServices.CallSite`1.MakeUpdateDelegate() 
    at System.Runtime.CompilerServices.CallSite`1.GetUpdateDelegate(T& addr) 
    at System.Runtime.CompilerServices.CallSite`1.GetUpdateDelegate() 
    at System.Runtime.CompilerServices.CallSite`1.Create(CallSiteBinder binder) 
    at System.Func`2.Invoke(T arg) 
    at Microsoft.Scripting.Runtime.DynamicOperations.GetOrCreateSite[T](CallSiteBinder siteBinder, Func`2 factory) 
    at Microsoft.Scripting.Runtime.DynamicOperations.GetOrCreateSite[T1,TResult](CallSiteBinder siteBinder) 
    at Microsoft.Scripting.Runtime.DynamicOperations.ConvertTo[T](Object obj) 
    at IronPython.Runtime.PythonContext.ScopeGetVariable[T](Scope scope, String name) 
    at Microsoft.Scripting.Hosting.ScriptScope.GetVariable[T](String name) 
    at Microsoft.Scripting.Hosting.ScriptScope.GetVariable[T](String name) 
    at python_in_appdomain.Program.Remoting() in C:\Users\dave\Documents\Visual Studio 2010\Projects\IronPythonTest\IronPythonTest\Program.cs:line 8 
3 
    at python_in_appdomain.Program.Main(String[] args) in C:\Users\dave\Documents\Visual Studio 2010\Projects\IronPythonTest\IronPythonTest\Program. 
cs:line 31 

錯誤是令人震驚的直截了當。它表示,期待這種行爲完全不受限制地訪問。有沒有辦法解決?爲什麼字典能正常工作,但我的變量不是?有沒有辦法讓IronPython像Dictionary一樣對待我的變量?我錯過了非常明顯的東西嗎?

非常感謝您的幫助。

更新2012年12月21日

我不停地插科打諢,並與合作的解決方案上來。像這樣創建AppDomain(使用相同的權限對象)可以讓所有的東西都起作用。

AppDomainSetup setup = new AppDomainSetup(); 
      setup.ApplicationBase = System.Environment.CurrentDirectory; 
AppDomain domain = AppDomain.CreateDomain("IPyEngine", new Evidence(), setup, pset); 

我不能說我完全理解爲什麼,但我可以看到,我不提供我組裝的證據我也沒有添加任何組件到信任列表。我不想把這個標記爲答案,直到我確信我沒有做任何愚蠢的事情。

回答

0

這是可疑的:

The Zone of the assembly that failed was: 
Internet 
The Url of the assembly that failed was: 
file:///C:/Users/dave/Documents/Visual Studio 2010/Projects/IronPythonTest/IronPythonTest/bin/Debug/Microsoft.Dynamic.DLL 

我不知道是否該文件有一個區標識符。你可以檢查文件屬性,並Unblock it if necessary

+0

我已經注意到,但並不知道這種阻塞無意義。我解開了所有的DLL並且問題依然存在。 –

+0

我確實發現了一些其他的東西。請參閱2012年12月21日的更新。 –