2011-05-12 22 views
0

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

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

public class NavigationBarViewModel 
{ 
    //... 

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

    } 

    //... 
} 

现在当然有担保属性应该以某种方式知道我们的安全上下文。我不确定从哪里开始,或者如果这真的是装饰者模式的应用程序。 Mabye有人可以将我指向正确的方向。

回答

0

因此,经过一些研究,我认为我发现了一种使用统一截取的交叉切割安全方法。我会分享我的代码:

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> 
+0

我要补充一点,你通常与这些拦截器的属性不会装修视图模型的方法,因为的ViewModels不应该由一个DI容器来解决,服务应该是。 – hoetz 2011-05-21 11:21:17