2011-05-12 61 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