Silverlight 4 MVVM:带有装饰器模式的横切安全性

发布于 2024-11-07 09:05:43 字数 698 浏览 0 评论 0原文

我们使用带有 PRISM 的 MVVM 和 Silverlight 4 开发了一个 Intranet 应用程序。到目前为止,我们只有一个基本的安全方案,可归结为基于活动目录组成员身份的“授予访问权限”或“拒绝访问”。现在我们必须对此进行扩展。

我们定义了更细粒度的角色和角色。在应用程序启动时加载的权限以及由单例 ISecurityContext 实例公开的权限。该安全上下文了解角色和角色。授予当前登录用户的权限。现在我想以一种优雅的方式将此上下文插入到我的视图模型中。我想做的一个简单的例子是:

public class NavigationBarViewModel
{
    //...

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

    }

    //...
}

现在当然,安全属性应该以某种方式了解我们的安全上下文。我不确定从哪里开始,或者这是否真的是装饰器模式的应用。 也许有人可以指出我正确的方向。

we have developed an intranet application with Silverlight 4 using MVVM with PRISM. Up until now we only had a basic security scheme which boils down to "access granted" or "access denied" based on active directory group membership. Now we have to expand on that.

We defined more granular roles & permissions which are being loaded at app startup and which are being exposed by a singleton ISecurityContext instance. This security context knows about the roles & permissions granted to the currently logged on user. Now I'd like to plug this context into my view models in an elegant way. A naive example of what I'd like to do is this:

public class NavigationBarViewModel
{
    //...

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

    }

    //...
}

Now of course the Secured Attribute should somehow be aware of our security context. I'm not sure where to start or if this would really be an application of the decorator pattern.
Mabye someone can point me into the right direction.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

戏蝶舞 2024-11-14 09:05:43

因此,经过一些研究,我认为我找到了一种使用 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>

So after some research I think I found a clean way for cross cutting security using Unity interception. I'll share my code:

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();
        }

    }

}

As you can see it's all about creating a custom HandlerAttribute which in turn calls a custom ICallHandler. In the CallHandler you can put your security related logic which will decide if the decorated method will be executed. You should throw some custom exceptions that you can catch from the layer using your methods. With that infrastructure in place, you can integrate any cross cutting modules in a clean way. Here's the config for the application since this can be a bit of a pain in Unity. Dont forget to add the Microsoft.Practices.Unity.InterceptionExtension namespace in your classes btw.

<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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文