C# WPF应用程序基于角色的访问控制-最佳实践

C# WPF应用程序基于角色的访问控制-最佳实践,c#,wpf,rbac,C#,Wpf,Rbac,我需要为我正在编写的WPF应用程序实现某种类型的。由于v2.0 ASP.NET具有安全性、成员资格和角色管理基础架构(例如所述),虽然我可以使用它,但我仍然觉得在这种情况下使用它会有点不方便。我欢迎任何使用过它并在类似环境中取得成功的人提供反馈 我还考虑过使用AD LDS,阅读了TechNet文章,并查看了一些MSDN代码示例,但我想知道是否有任何组件(针对.NET)可以消除创建数据库、设置数据库以进行部署和持续维护背后的一些固有复杂性。在这种情况下,免费或商业是可以的 关于这一点的其他问题提到

我需要为我正在编写的WPF应用程序实现某种类型的。由于v2.0 ASP.NET具有安全性、成员资格和角色管理基础架构(例如所述),虽然我可以使用它,但我仍然觉得在这种情况下使用它会有点不方便。我欢迎任何使用过它并在类似环境中取得成功的人提供反馈

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

关于这一点的其他问题提到了客户端应用程序服务,但这需要将IIS添加到组合中,这虽然不超出可能的范围,但在项目开始时我并没有想到这一点


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

您可以查看p&p指南/想法代码(或者您可以使用它们的块)

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

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

我构建了一个2层应用程序(WPF->SQLServer),增长了很多,管理层已经决定为了安全考虑,他们现在想要一个3层应用程序(WCF中间层)。我现在正在做这个,这是一个真正的痛苦,因为我把我的授权代码与客户端应用程序耦合得太紧密了。现在很明显,授权应该在服务层中进行,但需要做大量的工作

在如何识别特定的“安全”方面,我想出了一个很好的技巧,可以节省很多工作。虽然,具有讽刺意味的是,这是问题的一部分,我现在试图将其重新设计为3层。诀窍是使用类的完全限定名作为安全的唯一标识符,然后每次检查时都可以使用一些简单的代码:

_secUtil.PromptSecurityCheck(_secUtil.GetFullyQualifiedObjectName(this, "Save"))
下面是一些其他代码,让您了解我是如何做到这一点的(使用p&p框架)


错过了PnP关于该主题的指导,但之前遇到过AzMan。谢谢你!仅供大家参考。安全应用程序块在EntLib的v6中已被弃用。有关更多详细信息,请参阅处的迁移指南For AD LDS,如果您具有相应的权限,您可以将数据托管到AD存储中。希望这能为你简化事情?@code4life网上有这样的例子吗?我从这里开始:。仅供参考,AD LDS不一定比数据库更简单,只是不同而已。
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;

    }
}