2

プラグインを使用する C# アプリケーションを構築しています。アプリケーションは、プラグインがユーザーのマシン上で何をしても実行しないこと、およびアプリケーション自体よりも権限が少ないことをユーザーに保証する必要があります (たとえば、アプリケーションは独自のログ ファイルにアクセスできますが、プラグインはアクセスできません)。 .

3つの選択肢を考えました。

  1. System.AddIn を使用します。私はこの代替手段を最初に試しました。これは非常に強力だったからですが、何かを変更するたびに、7 つの異なるプロジェクトで同じコードを 7 回変更する必要があることに本当にがっかりしています。その上、単純な Hello World アプリケーションであっても解決すべき問題は膨大です。

  2. System.Activator.CreateInstance(assemblyName, typeName) を使用します。これは、以前のバージョンのアプリケーションで使用したものです。アクセス許可を制限する方法が提供されていないため、二度と使用できません。

  3. System.Activator.CreateInstance(AppDomain ドメイン、[...]) を使用します。それが私が今実装しようとしているものですが、それを行う唯一の方法は、使用されるすべてのクラスのシリアル化を必要とする ObjectHandle を通過することのようです。プラグインには WPF UserControls が含まれていますが、これはシリアル化できません。

UserControls またはその他のシリアル化できないオブジェクトを含むプラグインを作成し、それらのプラグインをカスタム PermissionSet で実行する方法はありますか?

4

1 に答える 1

1

できることの 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 ポリシーは非常に複雑であることで知られているため、このコードによって何かがポリシーをバイパスする可能性があるというリスクが常に存在します (YMMV :)

于 2010-03-13T13:45:31.040 に答える