您可以查看 P&P 指南/想法代码(或者您可以使用他们的块)。 http://msdn.microsoft.com/en-us/library/ff953196(v=pandp.50).aspx
我在 SQLServer 中实现了我自己的后端存储。它并不难,像 User、UserRole、SecurityItem、SecurityItemUser、SecurityItemRole 这样的表。我针对 AD 验证用户的 Windows 登录名,但只将他们的 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;
}
}