Вы можете посмотреть руководство P/& P для идей (или вы могли бы использовать их блок, возможно). http://msdn.microsoft.com/en-us/library/ff953196(v=pandp.50).aspx
Я реализовал собственный внутренний сервер в SQLServer. Это не так сложно, таблицы, такие как User, UserRole, SecurityItem, SecurityItemUser, SecurityItemRole. Я аутентифицирую входные данные пользователя Windows с помощью AD, но сохраняю только их имя входа в базу данных (например, ключ для таблицы User).
Это хорошая идея абстрагироваться от моделей интерфейсов/поставщиков. Таким образом, если ваше приложение изменится в будущем, для него не потребуется много рефакторинга.
Я построил двухуровневое приложение (WPF -> SQLServer), которое сильно выросло, и руководство решило в отношении безопасности, что теперь им требуется приложение с 3 уровнями (средний уровень WCF). Я сейчас работаю над этим, и это настоящая боль, потому что я слишком тесно связал свой код авторизации с клиентским приложением. Теперь очевидно, что авторизация должна выполняться на уровне обслуживания, но для этого потребуется много работы.
С точки зрения определения конкретного «защищаемого», я придумал хороший трюк, который экономит много работы. Хотя, по иронии судьбы, это часть проблемы, которую я сейчас пытаюсь перестроить на 3 уровня. Хитрость заключается в том, чтобы использовать полное имя класса в качестве уникального идентификатора для защищаемого, то вы можете использовать простой код каждый раз, когда вы проверяете:
_secUtil.PromptSecurityCheck(_secUtil.GetFullyQualifiedObjectName(this, "Save"))
Вот какой-то другой код, чтобы дать вам представление о том, насколько Я сделал это (используя P & P framework).
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;
}
}
Для AD LDS вы можете разместить данные в хранилище AD, если у вас есть соответствующие права. Надеюсь, это упростит вам дело? – code4life
@ code4life Любые примеры в Интернете? – noonand
Я бы начал здесь: http://msdn.microsoft.com/en-us/library/aa772138.aspx. Как FYI, AD LDS не обязательно делает вещи проще, чем база данных, просто разные. – code4life