2010-03-13 110 views
2

我正在构建一个使用插件的C#应用​​程序。应用程序必须向用户保证,插件不会在用户机器上执行任何他们想要的操作,并且应用程序本身的权限会更小(例如,应用程序可以访问自己的日志文件,而插件则不能) 。执行不可信代码

我考虑过三种选择。

  1. 使用System.AddIn。我首先尝试了这种方法,因为它的功能非常强大,但是我真的很失望,因为每次我想修改某些内容时,需要在七个不同的项目中修改相同的代码七次。此外,即使对于简单的Hello World应用程序也有大量的问题需要解决。

  2. 使用System.Activator.CreateInstance(assemblyName,typeName)。这是我在前一个版本的应用程序中使用的。我再也不能使用它了,因为它没有提供限制权限的方法。

  3. 使用System.Activator.CreateInstance(AppDomain域,[...])。这就是我现在要实现的目标,但似乎要做到这一点的唯一方法是通过ObjectHandle,这需要对每个使用的类进行序列化。尽管插件包含不可序列化的WPF UserControls。

那么,有没有一种方法来创建一个包含用户控件或其他非序列化对象的插件和一个自定义的PermissionSet执行这些插件?

回答

1

您可以做的一件事就是将当前AppDomain的策略级别设置为受限权限集,并添加证据标记以基于强名称或位置进行限制。最简单的做法可能是要求插件位于特定的目录中,并给它们一个限制性策略。

例如

public static void SetRestrictedLevel(Uri path) 
{ 
    PolicyLevel appDomainLevel = PolicyLevel.CreateAppDomainLevel();    

    // Create simple root policy normally with FullTrust 
    PolicyStatement fullPolicy = new PolicyStatement(appDomainLevel.GetNamedPermissionSet("FullTrust")); 
    UnionCodeGroup policyRoot = new UnionCodeGroup(new AllMembershipCondition(), fullPolicy); 

    // Build restrictred permission set 
    PermissionSet permSet = new PermissionSet(PermissionState.None);    
    permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));    
    PolicyStatement permissions = new PolicyStatement(permSet, PolicyStatementAttribute.Exclusive); 
    policyRoot.AddChild(new UnionCodeGroup(new UrlMembershipCondition(path.ToString()), permissions));    

    appDomainLevel.RootCodeGroup = policyRoot; 

    AppDomain.CurrentDomain.SetAppDomainPolicy(appDomainLevel); 
} 

static void RunPlugin() 
{ 
    try 
    {     
     SetRestrictedLevel(new Uri("file:///c:/plugins/*"));     

     Assembly a = Assembly.LoadFrom("file:///c:/plugins/ClassLibrary.dll"); 
     Type t = a.GetType("ClassLibrary.TestClass"); 
     /* Will throw an exception */     
     t.InvokeMember("DoSomething", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, 
       null, null, null); 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e.ToString()); 
    } 
} 

当然这不是严格的测试和CAS的政策是众所周知的复杂,所以总是有风险的,这个代码可以让一些东西绕过政策,因人而异:)

+0

感谢。我试过了,我认为这正是我需要的。 – 2010-03-14 11:42:42