2012-03-04 5 views
3

Мне нужно реализовать какой-то RBAC для приложения WPF, которое я пишу в данный момент. Так как v2.0 ASP.NET имеет инфраструктуру безопасности, членства и управления ролями (как описано, например, here), и, хотя я мог бы использовать это, все же кажется, что использовать его в этом контексте было бы немного хаки. Я буду приветствовать обратную связь от тех, кто ее использовал, и имел успех в аналогичном контексте.Контроль доступа на основе ролей для приложения WPF - лучшие практики

Я также рассмотрел использование AD LDS, прочитал статьи TechNet и рассмотрел некоторые образцы кода MSDN, но мне интересно, есть ли какой-либо компонент (для .NET), который устраняет некоторые из присущих ему сложностей создание базы данных, настройка ее для развертывания и текущее обслуживание. В этом случае бесплатный или коммерческий вариант.

Другие вопросы, касающиеся SO упоминают службы клиентских приложений, но это влечет за собой добавление IIS в микс, который, хотя и не выходит за рамки возможностей, был чем-то, что я не рассматривал в начале проекта.

Каковы наилучшие практики в этом случае? Приложение представляет собой типичное дело типа n-типа, которое говорит с удаленной базой данных SQL Server, поэтому возможности могут быть сохранены там, если это необходимо.

+1

Для AD LDS вы можете разместить данные в хранилище AD, если у вас есть соответствующие права. Надеюсь, это упростит вам дело? – code4life

+0

@ code4life Любые примеры в Интернете? – noonand

+1

Я бы начал здесь: http://msdn.microsoft.com/en-us/library/aa772138.aspx. Как FYI, AD LDS не обязательно делает вещи проще, чем база данных, просто разные. – code4life

ответ

5

Вы можете посмотреть руководство 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; 

    } 
} 
+0

Пропустил руководство PnP по этому предмету, но прежде встретил AzMan. Спасибо за это! – noonand

+1

Так же, как FYI для тех, кто кружится, чтобы прочитать это. Блок Application Security устарел в версии 6 EntLib. Для получения дополнительной информации см. Руководство по миграции по адресу http://go.microsoft.com/fwlink/p/?LinkID=290906 – noonand

Смежные вопросы