2012-03-04 73 views
3

我需要为目前正在编写的WPF应用程序实现某种RBAC。由于v2.0 ASP.NET具有安全性,成员资格和角色管理基础结构(例如,如here所述),虽然我可以使用它,但仍然觉得在这种情况下使用它会有点冒失。我会欢迎任何使用过它并在类似环境中取得成功的人的反馈。WPF应用程序的基于角色的访问控制 - 最佳实践

我也考虑过使用AD LDS,阅读TechNet文章,并查看了一些MSDN代码示例,但我想知道是否有任何组件(用于.NET),它可以消除一些固有的复杂性创建数据库,将其设置为部署和持续维护。在这种情况下免费或商业可以。

有关SO提及客户端应用服务的其他问题,但这需要将IIS添加到组合中,尽管没有超出可能性范围,但在项目开始时我并没有设想到这一点。

这种情况下的最佳做法是什么?该应用程序是一种典型的n层类型事务,与远程SQL Server数据库进行通信,以便在需要时可以将角色存储在那里

+1

对于AD LDS,如果您有适当的权限,则可以将数据托管到AD存储中。希望这会为你简化问题? – code4life 2012-03-05 16:12:33

+0

@ code4life在此网站上的任何示例? – noonand 2012-03-05 20:54:39

+1

我会从这里开始:http://msdn.microsoft.com/en-us/library/aa772138.aspx。作为参考,AD LDS不一定比数据库简单,只是不同而已。 – code4life 2012-03-05 21:16:23

回答

5

您可以查看P & P指导/代码(或你可以使用他们的块)。 http://msdn.microsoft.com/en-us/library/ff953196(v=pandp.50).aspx

我在SQLServer中实现了自己的后端存储。它并不那么难,像User,UserRole,SecurityItem,SecurityItemUser,SecurityItemRole这样的表。我根据AD对用户的Windows登录进行身份验证,但只将其登录名存储在数据库中(例如用户表的密钥)。

通过接口/提供者模型将事物抽象出来是一个好主意。这样,如果你的应用程序在未来发生变化,它不会需要太多的重构。

我构建了一个增长很多的2层应用程序(WPF - > SQLServer),并且管理层决定他们现在需要一个3层应用程序(WCF中间层)。我现在正在处理这个问题,而且这是一个真正的痛苦,因为我将授权代码与客户端应用程序密切配合。现在很明显授权应该发生在服务层,但需要很多工作。

关于如何识别特定的'安全',我想出了一个很好的窍门,节省了大量的工作。具有讽刺意味的是,虽然这是问题的一部分,但我现在试图对其进行3层重新设计。诀窍是作为唯一的标识符使用完全合格的名称类的一个可靠的,那么你可以使用一些简单的代码每次检查:

_secUtil.PromptSecurityCheck(_secUtil.GetFullyQualifiedObjectName(this, "Save")) 

下面是一些其他的代码给你一个想法如何我做到了(使用P & P框架)。

public class SecurityUtil : ISecurityUtil 
{ 
    public string DatabaseUserName { get { return LocalUserManager.GetUserName(); } } 

    public bool PromptSecurityCheck(string securityContext) 
    { 
     bool ret = IsAuthorized(securityContext); 

     if (!ret) 
     { 
      MessageBox.Show(string.Format("You are not authorised to perform the action '{0}'.", securityContext), Settings.Default.AppTitle, 
             MessageBoxButton.OK, MessageBoxImage.Error); 
     } 

     return ret; 
    } 

    public bool IsAuthorized(string securityContext) 
    { 
     IAuthorizationProvider ruleProvider = AuthorizationFactory.GetAuthorizationProvider("MyAuthorizationProvider"); 

     //bool ret = ruleProvider.Authorize(LocalUserManager.GetThreadPrinciple(), securityContext); 
     bool ret = ruleProvider.Authorize(LocalUserManager.GetCurrentPrinciple(), securityContext);    
     return ret; 
    } 

    public string GetFullyQualifiedName(object element) 
    { 
     return element.GetType().FullName; 
    } 

    public string GetFullyQualifiedObjectName(object hostControl, string objectName) 
    { 
     return GetFullyQualifiedName(hostControl) + "." + objectName; 
    } 
} 

[ConfigurationElementType(typeof(CustomAuthorizationProviderData))] 
public class MyAuthorizationProvider : AuthorizationProvider 
{ 
    public SitesAuthorizationProvider(NameValueCollection configurationItems) 
    { 
    } 

    public override bool Authorize(IPrincipal principal, string context) 
    { 

     bool ret = false; 

     if (principal.Identity.IsAuthenticated) 
     { 
      // check the security item key, otherwise check the screen uri 
      ret = LocalCacheManager.GetUserSecurityItemsCache(LocalUserManager.UserId, false).Exists(
       si => si.SecurityItemKey.Equals(context, StringComparison.InvariantCultureIgnoreCase)); 

      if (!ret) 
      { 
       // check if this item matches a screen uri 
       ret = LocalCacheManager.GetUserSecurityItemsCache(LocalUserManager.UserId, false).Exists(
       si => si.Uri.Equals(context, StringComparison.InvariantCultureIgnoreCase)); 
      } 
     } 

     return ret; 

    } 
} 
+0

错过了关于该主题的PnP指导,但之前曾遇到过AzMan。感谢那! – noonand 2012-03-05 12:00:00

+1

就像任何人回过头来阅读这篇文章一样。安全应用程序块已在EntLib的v6中被弃用。有关更多详细信息,请参阅http://go.microsoft.com/fwlink/p/?LinkID=290906上的迁移指南 – noonand 2013-11-26 10:08:21