Silverlight 4 MVVM: сквозная защита с рисунком декоратора - PullRequest
0 голосов
/ 12 мая 2011

мы разработали приложение для интрасети с Silverlight 4, используя MVVM с PRISM. До сих пор у нас была только базовая схема безопасности, которая сводилась к «доступу предоставлен» или «доступ запрещен» на основе членства в активной группе каталогов. Теперь мы должны расширить это.

Мы определили более детализированные роли и разрешения, которые загружаются при запуске приложения и открываются одноэлементным экземпляром ISecurityContext. Этот контекст безопасности знает о ролях и разрешениях, предоставленных текущему вошедшему в систему пользователю. Теперь я хотел бы элегантно включить этот контекст в мои модели представлений. Наивный пример того, что я хотел бы сделать, это:

public class NavigationBarViewModel
{
    //...

    [Secured(RequiredPermission="EditLocation")]
    public void NavigateToEditLocations(IRegionManager rManager)
    {
        var editLocView = new Uri("EditLocationsView", UriKind.Relative);
        rManager.RequestNavigate("WorkspaceRegion", editLocView);

    }

    //...
}

Теперь, конечно, Защищенный атрибут должен как-то знать о нашем контексте безопасности. Я не уверен, с чего начать, или если это действительно будет применение шаблона декоратора. Мэйби, кто-то может указать мне правильное направление.

1 Ответ

0 голосов
/ 16 мая 2011

Так что после некоторого исследования, я думаю, я нашел чистый способ сквозного обеспечения безопасности с помощью перехвата Unity.Я поделюсь своим кодом:

public class MyCallHandler: ICallHandler
{

    private readonly string[] roles;

    public MyCallHandler(params string[] roles)
    {
        this.roles = roles;
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        IPrincipal principal = Thread.CurrentPrincipal;
        bool allowed = roles.Any(principal.IsInRole);
        if (!allowed)
            return input.CreateExceptionMethodReturn(new
                                         Exception("Security exception!"));
        return getNext()(input, getNext);

    }

    public int Order
    {
        get;
        set;
    }
}

public class MethodAccessAttribute : HandlerAttribute
{
    private readonly string[] roles;

    public MethodAccessAttribute(params string[] roles)
    {
        this.roles = roles;
    }

    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new MyCallHandler(roles);
    }
}

public interface IConsoleThingie
{
    [MethodAccess("admin")]
    void SomeMethod();
}

public class MyConsoleThing : IConsoleThingie
{
    public void SomeMethod()
    {
        Console.WriteLine("test");
    }
}

class Program
{
    static void Main(string[] args)
    {
        IUnityContainer container = new UnityContainer();
        container.AddNewExtension<Interception>();
        container.RegisterType<IConsoleThingie, MyConsoleThing>().Configure<Interception>().SetInterceptorFor<IConsoleThingie>(new InterfaceInterceptor());

        IConsoleThingie thing = container.Resolve<IConsoleThingie>();
        try
        {
            thing.SomeMethod();
        }
        catch
        {
            Console.WriteLine("More granular exception handling here");
            Console.ReadLine();
        }

    }

}

Как вы можете видеть, все дело в создании пользовательского атрибута HandlerAttribute, который в свою очередь вызывает пользовательский ICallHandler.В CallHandler вы можете поместить свою логику, связанную с безопасностью, которая будет определять, будет ли выполнен декорированный метод.Вы должны выдать несколько пользовательских исключений, которые вы можете поймать из слоя, используя ваши методы.Имея эту инфраструктуру, вы можете без проблем интегрировать любые сквозные модули.Вот конфигурация для приложения, так как это может быть немного болезненно в Unity.Не забудьте добавить пространство имен Microsoft.Practices.Unity.InterceptionExtension в ваши классы, кстати.

<configuration>
 <configSections>
<section name="unity"
    type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
            Microsoft.Practices.Unity.Configuration" />
 </configSections>
  <unity>
   <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>
<containers>

  <container>
    <extension type="Interception" />
    <register type="IConsoleThingie" mapTo="MyConsoleThing">
      <interceptor type="InterfaceInterceptor" />
      <policyInjection />
    </register>

    <types>
    </types>

  </container>
</containers>
 </unity>
  </configuration>
...