2009-08-31 110 views
8

我刚才问了如何限制插件访问(我想阻止他们写入磁盘或网络),并且我被告知要使用AppDomain。我已经搜索,并尝试和失败,如何得到这个工作。限制插件通过appdomain访问文件系统和网络

任何人都可以提供一些信息,所以我可以开始,简单地把一个AppDomain,不允许写入文件或网络。

回答

5

我想这是你需要的,如果我正确理解你的观点。

System.Security.PermissionSet ps = 
    new System.Security.PermissionSet(System.Security.Permissions.PermissionState.None); 
ps.AddPermission(new System.Security.Permissions.FileIOPermission(System.Security.Permissions.FileIOPermissionAccess.NoAccess, "C:\\")); 
System.Security.Policy.PolicyLevel pl = System.Security.Policy.PolicyLevel.CreateAppDomainLevel(); 
pl.RootCodeGroup.PolicyStatement = new System.Security.Policy.PolicyStatement(ps); 
AppDomain.CurrentDomain.SetAppDomainPolicy(pl); 
System.Reflection.Assembly myPluginAssembly = AppDomain.CurrentDomain.Load("MyPluginAssembly"); 

这更确切地说是你的意思吗?

请注意,您可能会提供一个包含不希望插件访问的路径的字符串数组。您可以提供是否在初始化FileIOPermission类的新实例时。

让我知道这是否有帮助。 :-)

+0

这似乎是exacly im后,我得到给定的程序集名称或代码库是无效的。 (从HRESULT异常:0x80131047)现在,但我还没有时间去更多地了解它(我可以猜测做错了什么)。 明天我得到更多的时间,我会让你知道 – EKS 2009-09-01 22:00:25

+0

所以,最后,这是你在找什么?我想,因为你似乎已经检查过它。 :-) – 2009-09-11 16:27:11

+0

@EKS您必须从相同的文件夹或文件夹的其中一个子文件加载。 – 2009-10-16 08:15:38

0

如果您使用的是插件,您可能会了解代理。

在通过代理加载您的程序集时,如果我没有记错,您可以通过LoadAssembly()方法指定此特定程序集的安全策略级别。换句话说,这是通过反思完成的。

我知道我的答案没有那么详细,但我希望它能让你知道在哪里寻找解决方案。我会留意找出有关这个问题的更多细节,以便我可以得到更好的帮助。 =)

希望你会分享你的发现,当你做完它。

15

对于.net framework 4.0,请按照以下代码从this MSDN文章。

以下示例实现了上一节中的过程。在该示例中,Visual Studio解决方案中名为Sandboxer的项目还包含名为UntrustedCode的项目,该项目实现UntrustedClass类。此方案假定您已下载库程序集,其中包含预期返回true或false的方法,以指示您提供的数字是否为斐波纳契数字。相反,该方法尝试从您的计算机读取文件。以下示例显示了不可信代码。

using System; 
using System.IO; 
namespace UntrustedCode 
{ 
    public class UntrustedClass 
    { 
     // Pretend to be a method checking if a number is a Fibonacci 
     // but which actually attempts to read a file. 
     public static bool IsFibonacci(int number) 
     { 
      File.ReadAllText("C:\\Temp\\file.txt"); 
      return false; 
     } 
    } 
} 

以下示例显示了执行非信任代码的Sandboxer应用程序代码。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO; 
using System.Security; 
using System.Security.Policy; 
using System.Security.Permissions; 
using System.Reflection; 
using System.Runtime.Remoting; 

//The Sandboxer class needs to derive from MarshalByRefObject so that we can create it in another 
// AppDomain and refer to it from the default AppDomain. 
class Sandboxer : MarshalByRefObject 
{ 
    const string pathToUntrusted = @"..\..\..\UntrustedCode\bin\Debug"; 
    const string untrustedAssembly = "UntrustedCode"; 
    const string untrustedClass = "UntrustedCode.UntrustedClass"; 
    const string entryPoint = "IsFibonacci"; 
    private static Object[] parameters = { 45 }; 
    static void Main() 
    { 
     //Setting the AppDomainSetup. It is very important to set the ApplicationBase to a folder 
     //other than the one in which the sandboxer resides. 
     AppDomainSetup adSetup = new AppDomainSetup(); 
     adSetup.ApplicationBase = Path.GetFullPath(pathToUntrusted); 

     //Setting the permissions for the AppDomain. We give the permission to execute and to 
     //read/discover the location where the untrusted code is loaded. 
     PermissionSet permSet = new PermissionSet(PermissionState.None); 
     permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); 

     //We want the sandboxer assembly's strong name, so that we can add it to the full trust list. 
     StrongName fullTrustAssembly = typeof(Sandboxer).Assembly.Evidence.GetHostEvidence<StrongName>(); 

     //Now we have everything we need to create the AppDomain, so let's create it. 
     AppDomain newDomain = AppDomain.CreateDomain("Sandbox", null, adSetup, permSet, fullTrustAssembly); 

     //Use CreateInstanceFrom to load an instance of the Sandboxer class into the 
     //new AppDomain. 
     ObjectHandle handle = Activator.CreateInstanceFrom(
      newDomain, typeof(Sandboxer).Assembly.ManifestModule.FullyQualifiedName, 
      typeof(Sandboxer).FullName 
      ); 
     //Unwrap the new domain instance into a reference in this domain and use it to execute the 
     //untrusted code. 
     Sandboxer newDomainInstance = (Sandboxer) handle.Unwrap(); 
     newDomainInstance.ExecuteUntrustedCode(untrustedAssembly, untrustedClass, entryPoint, parameters); 
    } 
    public void ExecuteUntrustedCode(string assemblyName, string typeName, string entryPoint, Object[] parameters) 
    { 
     //Load the MethodInfo for a method in the new Assembly. This might be a method you know, or 
     //you can use Assembly.EntryPoint to get to the main function in an executable. 
     MethodInfo target = Assembly.Load(assemblyName).GetType(typeName).GetMethod(entryPoint); 
     try 
     { 
      //Now invoke the method. 
      bool retVal = (bool)target.Invoke(null, parameters); 
     } 
     catch (Exception ex) 
     { 
      // When we print informations from a SecurityException extra information can be printed if we are 
      //calling it with a full-trust stack. 
      (new PermissionSet(PermissionState.Unrestricted)).Assert(); 
      Console.WriteLine("SecurityException caught:\n{0}", ex.ToString()); 
      CodeAccessPermission.RevertAssert(); 
      Console.ReadLine(); 
     } 
    } 
}