Пользовательская авторизация в Asp.net WebApi - какой беспорядок?
Я читаю из нескольких ресурсов (книги и ответы 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 or
base.OnAuthorization`?
-
3) Это как они его построили? что если ответ равен нулю, то все в порядке? (случай № 2)
Н.Б.
Обратите внимание: я использую (и хочу использовать) только AuthorizeAttribute
, который уже наследует от AuthorizationFilterAttribute
Почему?
Becuase Я нахожусь на первом этапе: http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api
![enter image description here]()
В любом случае, я спрашиваю через расширение атрибута Authorize.
Ответы
Ответ 1
Какие методы следует использовать: IsAuthorized или OnAuthorization? ( или когда использовать, который)
Расширяется AuthorizationFilterAttribute
, если ваша логика авторизации не зависит от установленного идентификатора и ролей. Для авторизации, связанной с пользователем, вы будете расширять и использовать AuthorizeAttribute
. В первом случае вы переопределите OnAuthorization
. В последнем случае вы переопределите IsAuthorized
. Как вы могли видеть из исходного кода этих атрибутов, OnAuthorization
помечен как виртуальный, чтобы вы могли переопределить, если вы выходите из AuthorizationFilterAttribute
. С другой стороны, метод IsAuthorized
помечен как виртуальный AuthorizeAttribute
. Я считаю, что это хороший указатель на предполагаемое использование.
когда я должен вызвать base.IsAuthorized или base.OnAuthorization?
Ответ на этот вопрос заключается в том, как работает OO. Если вы переопределяете метод, вы можете либо полностью обеспечить новую реализацию, либо вернуть реалистичность, предоставляемую родителем, и улучшить поведение. Например, возьмите случай 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;
}
Извините, но не понимаю ваш Q3. BTW, фильтр авторизации существует уже давно, и люди используют его для всех видов вещей, а иногда и неправильно.
Еще одна вещь. И, наконец, здесь был этот парень, который сказал: "Ты не следует переопределять 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. В ASP.NET Web API существует еще один фильтр, называемый фильтром проверки подлинности. Идея заключается в том, что вы используете это для проверки подлинности и авторизации для авторизации, как указано в названии. Тем не менее, есть много примеров, когда эта граница испорчена. Многие примеры фильтров для автозавершения сделают некоторую аутентификацию. В любом случае, если у вас есть время и вы хотите понять немного больше, взгляните на эту статью MSDN . Отказ от ответственности: он был написан мной.
Ответ 2
Хорошо, мое предложение состоит в том, чтобы сделать следующее, предполагая, что вы используете токены на предъявителя OAuth для защиты вашего веб-API, и вы устанавливаете допустимое время в качестве требования для пользователя, когда вы выдали токен. Вы можете прочитать больше о аутентификации на токене здесь
- Создать атрибут CustomAuthorizeAttribute, который происходит из AuthorizationFilterAttribute
-
переопределить метод 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);
}
}
- Теперь в ваших контроллерах вы используете атрибут CustomAuthorize для защиты ваших контроллеров с использованием этой логики авторизации.
Ответ 3
ASP.NET v5 Внедрена совершенно новая система авторизации.
Для тех, кто собирается использовать .NET 5, я бы предложил перейти в Microsoft.AspNet.Authorization.
В значительной степени это обертывает беспорядок, вызванный тем, что
System.Web.Http.Authorize
и System.Web.Mvc.Authorize
и других старых реализаций аутентификации.
Он обеспечивает очень хорошую абстракцию типов действий (создание, чтение, обновление, удаление), ресурсов, ролей, претензий, просмотров, пользовательских требований и позволяет создавать пользовательские обработчики, объединяя любой из вышеперечисленных.
Кроме того, эти обработчики также могут использоваться в комбинации.
В ASP.NET v5 авторизация теперь предоставляет простую декларативную роль и более богатая политическая модель, где авторизация выражается в требования и обработчики оценивают претензии пользователей против требования. Императивные проверки могут основываться на простых правилах или которые оценивают как идентификацию пользователя, так и свойства ресурс, к которому пользователь пытается получить доступ.