Пользовательская авторизация (разрешения) ASP.NET MVC

В моем приложении роль имеет несколько разрешений. И я хочу, чтобы пользователи имели доступ к действиям, зависящим от разрешения, а не от роли.

Итак, предположим:

  • У администратора есть перм1, перм2, перм3,
  • SuperAdmin имеет все права, которые есть у администратора + perm4 и perm5.
  • Также есть несколько младших парней, у которых перм1, перм3, перм6, перм7.

Я хочу сделать следующее: я хочу, чтобы действие было доступно парню, у которого есть предположим, perm3 или perm4. эти два разрешения принадлежат двум разным ролям. но помимо perm3 Admin имеет perm1 и perm2, это действие будет доступно и младшим парням, у которых есть perm3 (не обязательно быть админом или суперадмином).

Итак, вы понимаете, что я имею в виду, верно? Я хочу реализовать это в ASP.NET MVC 4. Поэтому я полагаю, что мне нужно будет сделать свой собственный AuthorizeAttribute, мой собственный IIdentity и написать некоторые методы в global.asax. Также есть членство в ASP.NET. Нужно ли мне его трогать? Я не знаю, как собрать все вещи вместе. Может кто-нибудь мне помочь?


person Dimitri    schedule 22.10.2013    source источник
comment
Вы можете использовать встроенную функцию asp.net, которая использует аутентификацию на основе утверждений. Перейдите по ссылке для получения более подробной информации visualstudiomagazine .com/articles/2013/08/01/   -  person hungrycoder    schedule 22.10.2013


Ответы (2)


В основном вам нужно создать свой собственный AuthorizeAttribute, но использовать IIdentity из .NET. То, что вы описали здесь, представляет собой систему аутентификации и авторизации на основе утверждений.

Скорее всего, вам придется отказаться от членства в ASP.NET или использовать только его часть. Насколько я знаю, он построен не с расчетом на претензии.

В .NET 4.5 ребята добавили класс ClaimsPrincipal, реализующий интерфейс IPrincipal. Этот класс можно использовать для реализации пользовательской проверки подлинности и авторизации на основе утверждений.

Итак, когда пользователь аутентифицирован, вы можете добавить утверждения в поток:

var id = new ClaimsIdentity(claims, "Dummy");
var principal = new ClaimsPrincipal(new[] { id });
Thread.CurrentPrincipal = principal;

а затем просто используйте утверждения, которые вы найдете в Thread.CurrentPrincipal.

В ASP.NET MVC вы можете выполнить следующие шаги:

  1. создайте обработчик делегирования, который аутентифицирует пользователя. Если пользователь аутентифицирован, утверждения добавляются к участнику потока. В идеале этот делегирующий обработчик должен находиться как можно выше по цепочке, чтобы утверждения были доступны повсюду в цепочке выполнения. Также не забудьте установить HttpContext.Current.User с тем же принципалом

    открытый класс AuthHandler: DelegatingHandler{

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
    //authenticate user
    //get claims
    //create principal
    var newPrincipal = CreatePrincipal(claims);
    Thread.CurrentPrincipal = newPrincipal;
    if (HttpContext.Current != null)
         HttpContext.Current.User = newPrincipal;
    return await base.SendAsync(request, cancellationToken);
    }
    

    }

  2. Создайте фильтр, который авторизуется на основе утверждений, добавленных к участнику потока. Здесь вы можете сделать что-то вроде сравнения текущего маршрута с информацией, найденной в заявках.

person George Onofrei    schedule 22.10.2013

Итак, я думаю, что вы говорите: ActionA доступен, только если у пользователя есть perm1, perm2, и аналогично ActionB доступен, когда у пользователя есть perm1 и perm3.

Код, который я дал для иллюстрации, я его не компилировал. Но дам вам представление о подходе, который я излагаю

ШАГ 1. Вы можете приступить к созданию перечисления разрешений с атрибутом Flags.

ШАГ 2. Добавьте утверждения к текущему участнику на основе разрешения пользователя, хранящегося в вашем хранилище данных.

ШАГ 3. При вызове Action разрешите доступ к претензиям

[Flags]
    enum PermType
    {
        None = 0x0,
        Perm1 = 0x1,
        perm2 = 0x2,
        perm3 = 0x4,
        perm4 = 0x8,
        perm5 = 0x10 
    }

Добавление утверждений в CurrentPrincipal

var currentPrincipal = ClaimsPrincipal.Current;
var cms = currentPrincipal.Claims;
var permissions = PermType.Perm1 | PermType.perm2;
var claims = cms.ToList();
claims.Add(new Claim("Action1", permissions.ToString()));
claims.Add(new Claim("Action2", permissions.ToString()));
claims.Add(new Claim("Action3", permissions.ToString()));
System.Threading.Thread.CurrentPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims));

проверить, может ли пользователь получить доступ к определенному действию

public bool CanAccessThisAction(string acionName,PermType requiredPerms)
{
    var claim = principal.Claims.FirstOrDefault(c => c.Type == acionName);
    if (customPermissionClaim != null)
    {
        //check if required permission is present in claims for this user
        //return true/false
    }
    return false;
}

в действии

public ActionResult TestAction(string id)
{
    if(CanAccessThisAction("TestAction",PermType.Perm1|PermType.perm3|PermType.perm5))
    {
        //do your work here
    }
    else
    {
        //redirect user to some other page which says user is not authorized
    }
}
person Prerak K    schedule 22.10.2013
comment
Также вы можете попробовать ClaimsAuthorizationManager msdn.microsoft. com/ru-ru/library/ - person Prerak K; 22.10.2013