Кастомная авторизация в Asp.net WebApi - что за бардак?

113

Я читаю несколько ресурсов (книги и SO-ответы) об авторизации в WebApi.

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

Случай 1

Я видел такой подход переопределения OnAuthorization , который устанавливает реакцию, если что-то не так.

public class AllowOnlyCertainUsers : AuthorizeAttribute
{
 public override void OnAuthorization(HttpActionContext actionContext)
  {
   if ( /*check if user OK or not*/)
   {
     actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
   }
  }
}

Дело # 2

Но я также видел этот аналогичный пример, который также переопределяет, OnAuthorizationно с вызовом base:

public override void OnAuthorization(HttpActionContext actionContext) 
{ 
  base.OnAuthorization(actionContext);

    // If not authorized at all, don't bother

    if (actionContext.Response == null)  
     {
      //...
     }
}

Затем вы проверяете, установлен ли HttpActionContext.Responseон или нет. Если он не установлен, это означает, что запрос авторизован и пользователь в порядке.

Дело # 3

Но я также видел такой подход к переопределению IsAuthorized :

public class AllowOnlyCertainUsers : AuthorizeAttribute
{
 protected override bool IsAuthorized(HttpActionContext context)
  {
   if ( /*check if user OK or not*/)
   {
    return true;// or false
   }
  }
}

Дело # 4

А потом я увидел похожий пример, но с вызовом base.IsAuthorized (context):

protected override bool IsAuthorized(HttpActionContext context)
{
 if (something1 && something2 && base.IsAuthorized(context)) //??
 return true;
 return false;
}

Еще кое-что

И наконец Доминик сказал здесь :

Вы не должны переопределять OnAuthorization - потому что вам будет не хватать обработки [AllowAnonymous].

Вопросы

  • 1) Какие методы использовать: IsAuthorizedили OnAuthorization? (или когда использовать какой)

  • 2) когда мне звонить в base.IsAuthorized orbase.OnAuthorization`?

  • 3) Так они это построили? что если ответ нулевой, то все в порядке? (случай №2)

NB

Обратите внимание, я использую (и хочу использовать) только то, AuthorizeAttributeчто уже унаследовано от AuthorizationFilterAttribute

Зачем ?

Потому что я нахожусь на первом этапе: http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

введите описание изображения здесь

В любом случае я спрашиваю через расширение атрибута Authorize.

Ройи Намир
источник
Что нужно для переопределения атрибута Authorize? Какого варианта использования вы хотите достичь? Если вам нужно разрешить доступ для определенных пользователей, почему бы не использовать такой атрибут [Authorize (Users = "Admin")]?
Taiseer Joudeh
1
@TaiseerJoudeh Например, попробуйте авторизовать пользователей с 10:00 до 12:00 (настраивается). вы не можете сделать это с простыми ролями и авторизованным атрибутом. вы должны
придумать

Ответы:

93

Какие методы мне следует использовать: IsAuthorized или OnAuthorization? (или когда использовать какой)

Вы будете расширены, AuthorizationFilterAttributeесли ваша логика авторизации не зависит от установленной личности и ролей. Для авторизации, связанной с пользователем, вы будете расширять и использовать AuthorizeAttribute. В первом случае вы переопределите OnAuthorization. В последнем случае вы переопределите IsAuthorized. Как вы могли видеть из исходного кода этих атрибутов, они OnAuthorizationпомечены как виртуальные, чтобы вы могли их переопределить, если вы производите от них AuthorizationFilterAttribute. С другой стороны, IsAuthorizedметод отмечен как виртуальный в AuthorizeAttribute. Я считаю, что это хороший указатель на предполагаемое использование.

когда мне следует позвонить в base.IsAuthorized или base.OnAuthorization?

Ответ на этот вопрос заключается в том, как в целом работает объектно-ориентированный объект. Если вы переопределяете метод, вы можете либо полностью предоставить новую реализацию, либо использовать реализацию, предоставленную родителем, и улучшить поведение. Например, возьмем случай IsAuthorized(HttpActionContext). Поведение базового класса - проверить пользователя / роль на соответствие тому, что указано в фильтре, и установленной идентичности. Скажем, вы хотите сделать все это, но, кроме того, вы хотите проверить что-то еще, возможно, на основе заголовка запроса или чего-то еще. В этом случае вы можете предоставить такое переопределение.

protected override bool IsAuthorized(HttpActionContext actionContext)
{
    bool isAuthroized = base.IsAuthorized(actionContext);
    // Here you look at the header and do your additional stuff based on actionContext
    // and store the result in isRequestHeaderOk
    // Then, you can combine the results
    // return isAuthorized && isRequestHeaderOk;
}

Извините, но не понимаю ваш вопрос 3. Кстати, фильтр авторизации существует уже давно, и люди используют его для всех видов вещей, а иногда и неправильно.

Еще кое-что. И, наконец, здесь был парень, который сказал: «Вы не должны переопределять OnAuthorization - потому что вам будет не хватать обработки [AllowAnonymous]».

Парень, который сказал, что это Бог контроля доступа - Доминик. Очевидно, это будет правильно. Если вы посмотрите на реализацию OnAuthorization(скопировано ниже),

public override void OnAuthorization(HttpActionContext actionContext)
{
    if (actionContext == null)
    {
        throw Error.ArgumentNull("actionContext");
    }

    if (SkipAuthorization(actionContext))
    {
        return;
    }

    if (!IsAuthorized(actionContext))
    {
        HandleUnauthorizedRequest(actionContext);
    }
}

вызов SkipAuthorization- это та часть, которая обеспечивает применение AllowAnonymousфильтров, то есть пропуск авторизации. Если вы переопределите этот метод, вы потеряете это поведение. На самом деле, если вы решите основывать свою авторизацию на пользователях / ролях, на этом этапе вы бы решили наследовать AuthorizeAttribute. Единственный правильный вариант, который вам останется на этом этапе, - это переопределить, IsAuthorizedа не уже переопределенный OnAuthorization, хотя технически это возможно сделать и то, и другое.

PS. В веб-API ASP.NET есть еще один фильтр, называемый фильтром проверки подлинности. Идея состоит в том, что вы используете это для аутентификации и фильтр авторизации для авторизации, как указывает название. Однако есть множество примеров, когда эта граница не соответствует действительности. Многие примеры фильтров авторизации будут выполнять какую-то аутентификацию. В любом случае, если у вас есть время и вы хотите понять немного больше, взгляните на эту статью MSDN . Отказ от ответственности: это написал я.

Бадри
источник
Еще раз спасибо, но если я читаю между строк, IsAuthenticated вызывается OnAuthirization, так почему бы не переопределить OnAuthorization и не вызвать base.OnAuthorization, а затем проверить ответ?
Рой Намир
Конечно, можете, если вы этого хотите.
Бадри
В моем третьем вопросе я имел в виду: после запуска базовой функции, например base.OnAuthorization, единственный способ проверить, была ли она успешной - это проверить свойство Response ?, ps примеры взяты из вашей книги :-)
Рой Намир
Да, обычно вы ищете код состояния 401, но не ноль, насколько мне известно. Кстати, я не помню, чтобы писал OnAuthorizationв своей книге о переопределении . Я уверен, что не написал бы о проверке ответа на null, потому что я впервые слышу об этом :)
Бадри
Да перепуталась с другой книгой. Читаю одновременно 3 книги: Securty (ваша), практическая (ваша) и webapi pro (Tugberk's, Zeitler, Ali). Как вы можете видеть - они сделали это там: i.stack.imgur.com/LNGi4.jpg - они просто проверили, является ли значение null, поэтому я должен проверять нулевые коды или коды ошибок?
Рой Намир
18

Хорошо, я предлагаю сделать следующее, предполагая, что вы используете токены носителя OAuth для защиты своего веб-API, и вы устанавливаете allowedTime в качестве утверждения для пользователя при выдаче токена. Вы можете узнать больше об аутентификации на основе токенов здесь

  1. Создайте CustomAuthorizeAttribute, производный от AuthorizationFilterAttribute.
  2. переопределить метод OnAuthorizationAsyncи использовать пример кода ниже:

     public class CustomAuthorizeAttribute : AuthorizationFilterAttribute
    {
    
        public override Task OnAuthorizationAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
        {
    
            var principal = actionContext.RequestContext.Principal as ClaimsPrincipal;
    
            if (!principal.Identity.IsAuthenticated)
            {
                return Task.FromResult<object>(null);
            }
    
            var userName = principal.FindFirst(ClaimTypes.Name).Value;
            var userAllowedTime = principal.FindFirst("userAllowedTime").Value;
    
            if (currentTime != userAllowedTime)
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Not allowed to access...bla bla");
                return Task.FromResult<object>(null);
            }
    
            //User is Authorized, complete execution
            return Task.FromResult<object>(null);
    
        }
    }
    
  3. Теперь в ваших контроллерах вы используете атрибут CustomAuthorize для защиты контроллеров с помощью этой логики авторизации.
Тайсир Джудех
источник
1
Спасибо. Но в настоящее время я использую метод, AuthorizeAttributeкоторый наследуется, AuthorizationFilterAttributeа также для обучения я специально спросил, какой метод мне следует использовать, и о том, что ответ имеет контент или нет ...
Рой Намир
3

ASP.NET v5 представила совершенно новую систему авторизации. Тем, кто собирается использовать .NET 5, я предлагаю перейти на Microsoft.AspNet.Authorization.

В значительной степени это завершает беспорядок, вызванный сохранением как System.Web.Http.Authorizeи, так System.Web.Mvc.Authorizeи других старых реализаций аутентификации.

Он обеспечивает очень хорошую абстракцию типов действий (создание, чтение, обновление, удаление), ресурсов, ролей, утверждений, представлений, пользовательских требований и позволяет создавать собственные обработчики, комбинируя любые из вышеперечисленных. Кроме того, эти обработчики также можно использовать в комбинации.

В ASP.NET v5 авторизация теперь предоставляет простую декларативную роль и более богатую модель на основе политик, в которой авторизация выражается в требованиях, а обработчики оценивают утверждения пользователей на соответствие требованиям. Императивные проверки могут быть основаны на простых политиках или политиках, которые оценивают как личность пользователя, так и свойства ресурса, к которому пользователь пытается получить доступ.

Анестис Кивраноглу
источник
14
Полезно знать, но вообще не отвечает на вопрос.
Zero3