Ответ 1
Обновление июля 2014 года
Мой первоначальный ответ был посвящен WebApi 1. с помощью WebApi 2 произошли некоторые изменения, то есть теперь есть IAuthenticationFilter
, что означает, что вы можете переместить логику аутентификации из DelegatingHandler
, которая немного более элегантна.
Существует проект Nuget здесь, который предлагает реализацию IAuthenticationFilter, а также объясняет некоторые предпосылки его введения.
Средство промежуточного ПО OWIN теперь, пожалуй, лучшее место для реализации вашей логики аутентификации - здесь есть пример аутентификации сертификата здесь и базовая аутентификация OWIN Middleware здесь в этот пост в блоге прежний пример является предпочтительным, поскольку он демонстрирует использование базового класса AuthenticationHandler
.
Совет по AuthorizationFilters
остается практически неизменным.
Окончательное обновление
Как правило,...
Используйте DelegatingHandler
для выполнения проверки подлинности... то есть кто-то есть. Используйте это, чтобы установить Принцип контекста темы и пользователя, добавить претензии и т.д. Здесь вы можете разместить логику авторизации, но в достаточно глобальном масштабе. Я бы лично всегда использовал AuthorizationFilters для авторизации.
Используйте AuthorizationFilters
, чтобы ограничить контроллеры и действия конкретными людьми. Они используются, когда вы можете экстраполировать их разрешение с информацией в параметрах запроса, принципала, URL-адреса или http-запроса. Фильтр авторизации по умолчанию можно использовать для ограничения доступа к анонимным пользователям или ролям (если они установлены как нечто вроде обработчика делегирования) - очевидно, вы также можете реализовать свои собственные AuthorizationFilters, если вам это нужно.
Иногда используйте ActionFilters
, когда вам нужно принять решение о разрешении с использованием содержимого сообщения, например. вам нужен доступ к объекту на сущности, чтобы решить, имеют ли они доступ (очевидно, будьте осторожны с этим (!)).
Примечание:
AuthorizationFilters
вызывается до того, как содержимое тела будет прочитано, поэтому они не имеют доступа к телу сообщения для принятия решений о авторизации, поэтому ActionFilters
в частности OnActionExecuting
используется для случайного повышения ошибок аутентификации.
Так
В вашем сценарии я бы поставил простой DelegatingHandler
, чтобы взять ваш заголовок и установить принципал.
public class CustomAuthenticationMessageHandler : DelegatingHandler
{
public CustomAuthenticationMessageHandler ()
{
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
Authenticate(request);
return base.SendAsync(request, cancellationToken);
}
protected virtual void Authenticate(HttpRequestMessage request)
{
var authorisationHeader = request.Headers.Authorization;
if (authorisationHeader == null)
{
return;
}
//Ensure you are happy with the header contents then
{
var principal = new GenericPrincipal(//new Identity , //Roles);
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
}
}
}
Затем используйте AuthorizationFilters
для ограничения доступа:
[Authorize]
public string Get()
{
}
[Authorize(Roles = "Admin")]
public string GetAdminOnly()
{
}
Чтобы зарегистрировать глобальную проверку подлинности
config.MessageHandlers.Add(new CustomAuthenticationMessageHandler());
Это будет означать, что в каждом запросе принципал будет установлен как null, так и действительный идентификатор. Он не будет обрабатывать авторизацию, то есть не откажет в доступе к любым контроллерам или действиям.
Чтобы начать защиту ресурсов
Либо целевые защищенные контроллеры, либо действия со стандартными или пользовательскими атрибутами [Авторизовать]. Или зарегистрируйтесь глобально:
config.Filters.Add(new AuthorizeAttribute());
И только белый список контроллеров и действий, которые вы хотите получить без защиты, используя атрибут [AllowAnonymous]
.
Если вам нужна только проверка подлинности на некоторых маршрутах
Затем вы можете немного изменить свой DelegatingHandler
, чтобы установить InnerHandler
на правильный контроллер, например.
public CustomAuthenticationMessageHandler(HttpConfiguration configuration)
{
InnerHandler = new HttpRoutingDispatcher(configuration);
}
И затем вы можете указать этот обработчик на своих маршрутах так:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "myurl",
defaults: new {},
constraints: new {},
handler: new CustomAuthenticationHandler(config)
);