SORU
10 Kasım 2010, ÇARŞAMBA


Korumalı alan için pratik bir yol arıyorum .NET eklentileri

Erişim eklentileri için basit ve güvenli bir yol için bir arıyorum .NET uygulama. Bu çok yaygın bir gereklilik olduğunu düşünüyorum rağmen, tüm ihtiyaçlarımı karşılayan bir şey bulmak için mücadele ediyorum:

  • Ana uygulama keşfetmek ve zamanında eklenti onun derlemeler yükler
  • Eklentileri bilinmeyen 3. partiler tarafından oluşturulur, kötü niyetli kod yürütme engellemek için korumalı olmalıdır
  • Ortak birlikte çalışma derlemesi ana ve eklentileri her iki tarafından başvurulan tür içerir
  • Her eklenti Meclisi ortak bir eklenti arabirimi uygulayan bir veya daha fazla sınıfları içerir
  • Eklenti bir örnek başlatırken, ana bilgisayar arayüzü şeklinde kendisi için bir referans geçecek
  • Ana ortak arabirimi üzerinden eklenti içine arayacak ve plugins host aynı şekilde içine diyebilir
  • Ana ve eklentileri türleri birlikte çalışma derlemesi içinde tanımlanan formu (genel türler de dahil olmak üzere) veri alışverişi olur

Hem MEF ve MAF araştırdık, ama her ikisini tasarıyı uygun yapılmış olabilir görmek için mücadele ediyorum.

Benim anlayış doğru olduğunu varsayarsak, MAF başvurum için gerekli olan yalıtım sınırı üzerinde genel türler, geçen destek veremiyor. (MAF da çok karmaşık uygulamaktır, ama genel tür sorunu çözebilecek miyim bu ile çalışmaya hazır olacaktır.

MEF mükemmel bir çözümdür neredeyse, ama ev sahibi olarak aynı Türün uzantısı derlemeler yükler, ve bu nedenle, görünüşe göre korumalı alan engeller olarak güvenlik ihtiyacını kısa düşmek gibi görünüyor.

MEF korumalı modda çalışan konuşuyor this question, gördüm, ama nasıl tarif etmiyor. This post MEF kullanırken "uzantıları çalıştırmak için kötü amaçlı kod güven, veya Kod Erişimi Güvenlik" ama, yine de, nasıl tarif etmiyor. üzerinden teklif koruması gerektiğini belirtir Son olarak yüklenmesini bilinmeyen eklentileri önlemek için nasıl açıklar this post, var, ama bu bile yasal eklentileri bilinmeyen olacak benim durum için uygun değildir.

Başvuru başardı .NET 4.0 güvenlik öznitelikleri için benim derlemeler ve onlar doğru saygı ile MEF, ama anlayamıyorum, bu nasıl olur bana dışarıda malicous kod, gibi birçok çerçevesinde yöntem olabilir, bir güvenlik tehdidi (gibi yöntemleri System.IO.File) işaretli olarak SecuritySafeCritical anlamına gelir onlar erişilebilen SecurityTransparent derlemeleri. Bir şey mi kaçırıyorum? İnternet ayrıcalıkları derlemeler eklenti sunması gereken MEF söylemek için bazı ek bir adım var mı?

Son olarak da kendi basit korumalı eklenti benim mimarlık yaratmak, here anlatıldığı gibi ayrı bir Uygulama kullanarak baktım. Ancak, görebildiğim kadarıyla, bu teknik yalnızca bana geç sınıfları statik yöntemlerini çağırmak için bağlayıcı güvenilmeyen bir derleme kullanmak için izin verir. Ben denemek için uzatmak bu yaklaşım bir örnek oluşturmak için bir eklenti sınıfları, döndürülen örnek olamaz dökme ortak eklenti arabirimi anlamına gelir mümkün olmayan ana uygulama için arayın. Türü kesin olarak belirtilmiş, Uygulama etki alanı sınırları proxy erişim için işe yarar birkaç tekniği var mı?

Ben bu sorunun uzunluğu için özür dilerim; sebebi zaten, birisi yeni bir şey önerebilirsiniz umuduyla denemek için araştırdık tüm yollar göstermek için.

Fikirleriniz için çok teşekkürler, Tim

CEVAP
11 Kasım 2010, PERŞEMBE


Ben kabul Alastair Maw cevabı gibiydi onun önerisi ve bağlantıları led bana bir çalışılabilir bir çözüm, ama ben burada gönderme bazı ayrıntıları tam olarak ne yaptım, isteyen başka kim olabilir amaçlıyorsunuz benzer bir şey.

En basit şekliyle bir hatırlatma olarak, başvurumu üç derlemeler oluşmaktadır:

  • Ana uygulama montaj eklentileri tüketir
  • Birlikte çalışma derlemesi bir ortak tür uygulama ve eklentileri tarafından paylaşılan tanımlar
  • Örnek eklenti bir derleme

Aşağıdaki kodu kendi AppDomain: benim gerçek kod ve eklentileri bulup yüklemesi için gerekli olduğunu gösteren tek şey, basit bir versiyonu

Ana uygulama montaj ile başlayan, ana program sınıf Yardımcı Sınıf PluginFinder adlı belirlenmiş bir eklenti klasöründe herhangi bir derleme içinde eklenti türleri qualifiying bulmak için kullanır. Bu tiplerin her biri için, o zaman bir sandox AppDomain (ınternet bölge izinleri ile) bir örneğini oluşturur ve keşfedilen eklenti türünde bir örnek oluşturmak için kullanır.

Sınırlı izinlere sahip AppDomain Bir oluştururken, bu izinleri tabi olmayan bir veya daha fazla güvenilen derlemeler belirtmek mümkündür. Burada sunulan senaryo bunu yapmak için, Ana Uygulama derleme ve bağımlılıkları (birlikte çalışma derlemesi) imzalanmalıdır.

Her yüklenen eklenti örneğin, eklenti içinde özel yöntemler bilinen arayüzü üzerinden çağrılabilir ve eklenti da bilinen arabirimi üzerinden ana uygulamaya geri çağırabilirsiniz. Son olarak, ana uygulama sanal alanının da Kaldırır.

class Program
{
    static void Main()
    {
        var domains = new List<AppDomain>();
        var plugins = new List<PluginBase>();
        var types = PluginFinder.FindPlugins();
        var host = new Host();

        foreach (var type in types)
        {
            var domain = CreateSandboxDomain("Sandbox Domain", PluginFinder.PluginPath, SecurityZone.Internet);
            plugins.Add((PluginBase)domain.CreateInstanceAndUnwrap(type.AssemblyName, type.TypeName));
            domains.Add(domain);
        }

        foreach (var plugin in plugins)
        {
            plugin.Initialize(host);
            plugin.SaySomething();
            plugin.CallBackToHost();

            // To prove that the sandbox security is working we can call a plugin method that does something
            // dangerous, which throws an exception because the plugin assembly has insufficient permissions.
            //plugin.DoSomethingDangerous();
        }

        foreach (var domain in domains)
        {
            AppDomain.Unload(domain);
        }

        Console.ReadLine();
    }

    /// <summary>
    /// Returns a new <see cref="AppDomain"/> according to the specified criteria.
    /// </summary>
    /// <param name="name">The name to be assigned to the new instance.</param>
    /// <param name="path">The root folder path in which assemblies will be resolved.</param>
    /// <param name="zone">A <see cref="SecurityZone"/> that determines the permission set to be assigned to this instance.</param>
    /// <returns></returns>
    public static AppDomain CreateSandboxDomain(
        string name,
        string path,
        SecurityZone zone)
    {
        var setup = new AppDomainSetup { ApplicationBase = Path.GetFullPath(path) };

        var evidence = new Evidence();
        evidence.AddHostEvidence(new Zone(zone));
        var permissions = SecurityManager.GetStandardSandbox(evidence);

        var strongName = typeof(Program).Assembly.Evidence.GetHostEvidence<StrongName>();

        return AppDomain.CreateDomain(name, null, setup, permissions, strongName);
    }
}

Bu örnek kod, ana uygulama sınıfı çok basit, eklentileri tarafından çağrılabilir bu sadece bir yöntem olduğunu ortaya koyan. Ancak, bu sınıf, uygulama etki alanları arasında başvurulan olabilir MarshalByRefObject türetilmesi gerekir.

/// <summary>
/// The host class that exposes functionality that plugins may call.
/// </summary>
public class Host : MarshalByRefObject, IHost
{
    public void SaySomething()
    {
        Console.WriteLine("This is the host executing a method invoked by a plugin");
    }
}

PluginFinder sınıfı keşfetti eklenti türlerinin bir listesini verir tek bir ortak yöntem vardır. Bu keşif bulduğu yükler her derleme işlemi ve yansıma özellikli tipleri belirlemek için kullanır. Bu süreç, potansiyel olarak birçok meclisleri bile eklenti türlerini içeren bazı () yük Mayıs ayından bu yana da subsequntly yüklenmemiş olabilir ayrı uygulama etki alanında yürütülür. Bu sınıf aynı zamanda yukarıda açıklanan nedenlerle MarshalByRefObject devralır unutmayın. Beri örnekleri Type olmayabilir geçti arasında uygulama etki alanları, bu keşif süreci kullanan bir özel tür adı TypeLocator saklamak için string adı ve derleme adı keşfedilen her türü, hangi olabilir o zaman güvenli bir şekilde geçti geri ana applicatin etki alanı.

/// <summary>
/// Safely identifies assemblies within a designated plugin directory that contain qualifying plugin types.
/// </summary>
internal class PluginFinder : MarshalByRefObject
{
    internal const string PluginPath = @"..\..\..\Plugins\Output";

    private readonly Type _pluginBaseType;

    /// <summary>
    /// Initializes a new instance of the <see cref="PluginFinder"/> class.
    /// </summary>
    public PluginFinder()
    {
        // For some reason, compile-time types are not reference equal to the corresponding types referenced
        // in each plugin assembly, so equality must be tested by loading types by name from the Interop assembly.
        var interopAssemblyFile = Path.GetFullPath(Path.Combine(PluginPath, typeof(PluginBase).Assembly.GetName().Name)   ".dll");
        var interopAssembly = Assembly.LoadFrom(interopAssemblyFile);
        _pluginBaseType = interopAssembly.GetType(typeof(PluginBase).FullName);
    }

    /// <summary>
    /// Returns the name and assembly name of qualifying plugin classes found in assemblies within the designated plugin directory.
    /// </summary>
    /// <returns>An <see cref="IEnumerable{TypeLocator}"/> that represents the qualifying plugin types.</returns>
    public static IEnumerable<TypeLocator> FindPlugins()
    {
        AppDomain domain = null;

        try
        {
            domain = AppDomain.CreateDomain("Discovery Domain");

            var finder = (PluginFinder)domain.CreateInstanceAndUnwrap(typeof(PluginFinder).Assembly.FullName, typeof(PluginFinder).FullName);
            return finder.Find();
        }
        finally
        {
            if (domain != null)
            {
                AppDomain.Unload(domain);
            }
        }
    }

    /// <summary>
    /// Surveys the configured plugin path and returns the the set of types that qualify as plugin classes.
    /// </summary>
    /// <remarks>
    /// Since this method loads assemblies, it must be called from within a dedicated application domain that is subsequently unloaded.
    /// </remarks>
    private IEnumerable<TypeLocator> Find()
    {
        var result = new List<TypeLocator>();

        foreach (var file in Directory.GetFiles(Path.GetFullPath(PluginPath), "*.dll"))
        {
            try
            {
                var assembly = Assembly.LoadFrom(file);

                foreach (var type in assembly.GetExportedTypes())
                {
                    if (!type.Equals(_pluginBaseType) &&
                        _pluginBaseType.IsAssignableFrom(type))
                    {
                        result.Add(new TypeLocator(assembly.FullName, type.FullName));
                    }
                }
            }
            catch (Exception e)
            {
                // Ignore DLLs that are not .NET assemblies.
            }
        }

        return result;
    }
}

/// <summary>
/// Encapsulates the assembly name and type name for a <see cref="Type"/> in a serializable format.
/// </summary>
[Serializable]
internal class TypeLocator
{
    /// <summary>
    /// Initializes a new instance of the <see cref="TypeLocator"/> class.
    /// </summary>
    /// <param name="assemblyName">The name of the assembly containing the target type.</param>
    /// <param name="typeName">The name of the target type.</param>
    public TypeLocator(
        string assemblyName,
        string typeName)
    {
        if (string.IsNullOrEmpty(assemblyName)) throw new ArgumentNullException("assemblyName");
        if (string.IsNullOrEmpty(typeName)) throw new ArgumentNullException("typeName");

        AssemblyName = assemblyName;
        TypeName = typeName;
    }

    /// <summary>
    /// Gets the name of the assembly containing the target type.
    /// </summary>
    public string AssemblyName { get; private set; }

    /// <summary>
    /// Gets the name of the target type.
    /// </summary>
    public string TypeName { get; private set; }
}

Birlikte çalışma derlemesi eklentisi uygulayacak sınıflar için temel sınıf işlevselliği içerir (aynı zamanda MarshalByRefObject türetir unutmayın.

Bu Kurul da eklentileri geri ana uygulama çağırmasını sağlar IHost arabirim tanımlar.

/// <summary>
/// Defines the interface common to all untrusted plugins.
/// </summary>
public abstract class PluginBase : MarshalByRefObject
{
    public abstract void Initialize(IHost host);

    public abstract void SaySomething();

    public abstract void DoSomethingDangerous();

    public abstract void CallBackToHost();
}

/// <summary>
/// Defines the interface through which untrusted plugins automate the host.
/// </summary>
public interface IHost
{
    void SaySomething();
}

Son olarak, her eklenti temel sınıftan birlikte çalışma derlemesi içinde tanımlanan türetilmiş ve soyut yöntemlerini uygular. Birden fazla herhangi bir eklenti derleme sınıfları devralmasını olabilir ve birden fazla eklenti derlemeler olabilir.

public class Plugin : PluginBase
{
    private IHost _host;

    public override void Initialize(
        IHost host)
    {
        _host = host;
    }

    public override void SaySomething()
    {
        Console.WriteLine("This is a message issued by type: {0}", GetType().FullName);
    }

    public override void DoSomethingDangerous()
    {
        var x = File.ReadAllText(@"C:\Test.txt");
    }

    public override void CallBackToHost()
    {
        _host.SaySomething();           
    }
}

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • 8bitdigitaltv

    8bitdigitalt

    31 AĞUSTOS 2011
  • How To Cook That

    How To Cook

    16 NİSAN 2011
  • UniqueApps

    UniqueApps

    4 Ocak 2009