Поиск на сайте: Расширенный поиск


Новые программы oszone.net Читать ленту новостей RSS
CheckBootSpeed - это диагностический пакет на основе скриптов PowerShell, создающий отчет о скорости загрузки Windows 7 ...
Вы когда-нибудь хотели создать установочный диск Windows, который бы автоматически установил систему, не задавая вопросо...
Если после установки Windows XP у вас перестала загружаться Windows Vista или Windows 7, вам необходимо восстановить заг...
Программа подготовки документов и ведения учетных и отчетных данных по командировкам. Используются формы, утвержденные п...
Red Button – это мощная утилита для оптимизации и очистки всех актуальных клиентских версий операционной системы Windows...

Фильтры защиты в ASP.NET Web API

Текущий рейтинг: 1 (проголосовало 1)
 Посетителей: 1283 | Просмотров: 1646 (сегодня 0)  Шрифт: - +

Аутентификация и авторизация — краеугольные камни безопасности приложения. При аутентификации устанавливается идентификация пользователя проверкой предоставленных удостоверений, а при авторизации определяется, разрешено ли пользователю выполнять запрошенную операцию. Защищенная Web API аутентифицирует запросы и авторизует доступ к запрошенному ресурсу на основе установленной идентификации.

Реализовать аутентификацию в ASP.NET Web API можно с помощью точек расширения, доступных в конвейере ASP.NET Web API, а также с помощью некоторых средств, предоставляемых хостом. В первой версии ASP.NET Web API распространенной практикой было использование фильтра авторизации или фильтра операции для реализации аутентификации. В ASP.NET Web API 2 введен новый фильтр аутентификации, выделяемый процессу. Эта новая точка расширения обеспечивает четкое разделение обязанностей по аутентификации и авторизации. В этой статье я ознакомлю вас с этими двумя фильтрами защиты и покажу их применение для реализации аутентификации и авторизации как раздельных обязанностей в ASP.NET Web API.

Варианты для реализации аспектов защиты

Аутентификацию и авторизацию в ASP.NET Web API можно реализовать, используя точки расширения, предоставляемые хостом, а также точки расширения, доступные в самом конвейере ASP.NET Web API. Варианты на основе хоста включают HTTP-модули и промежуточные компоненты OWIN, тогда как варианты расширения ASP.NET Web API основаны на обработчиках сообщений, фильтрах операций, фильтрах авторизации и фильтрах аутентификации.

Варианты на основе хоста хорошо интегрируются в конвейер хоста и способны отклонять недопустимые запросы на ранних стадиях конвейера. Варианты расширения самой ASP.NET Web API, с другой стороны, предлагают более тонкий контроль над процессом аутентификации. То есть вы сможете указывать различные механизмы аутентификации для разных контроллеров и даже разные методы операций. Вам придется выбирать между более тесной интеграцией с хостом в сочетании с отклонением плохих запросов на ранних стадиях и более детальным управлением аутентификацией. Помимо этих общих характеристик, каждый вариант имеет свои плюсы и минусы, как я расскажу в последующих разделах.

HTTP-модуль Это вариант для Web API, выполняемой в IIS. HTTP-модули позволяют выполнять код защиты на ранних стадиях как часть конвейера IIS. Участник системы безопасности (principal), установленный из HTTP-модуля, доступен всем компонентам, в том числе компонентам IIS, выполняемым в конвейере позднее. Например, когда участник системы безопасности устанавливается HTTP-модулем в ответ на событие AuthenticateRequest, имя пользователя этого участника корректно регистрируется в поле cs-username в журналах IIS. Самый крупный недостаток с HTTP-модулями — отсутствие гранулярности. HTTP-модули выполняются для всех запросов, поступающих приложению. Для веб-приложения с различными возможностями, такими как генерация HTML-разметки, Web API и т. д., наличие HTTP-модуля, принудительно вызывающего аутентификацию одним способом, в целом не является достаточно гибким подходом. Другой недостаток при использовании HTTP-модуля — зависимость от хоста (в данном случае от IIS).

Промежуточные компоненты OWIN Это еще один вариант на основе хоста, доступный в случае OWIN-хостов. ASP.NET Web API 2 полностью поддерживает OWIN. Возможно, самая веская причина для использования промежуточного OWIN в целях защиты состоит в том, что те же самые промежуточные компоненты могут работать в разных инфраструктурах. То есть вы можете задействовать в своем приложении несколько инфраструктур, таких как ASP.NET Web API, SignalR и т. д., но применять общий промежуточный уровень безопасности. Однако минимальная гранулярность промежуточного уровня OWIN может оказаться недостаточной, так как он выполняется в конвейере OWIN и обычно вызывается для всех запросов. Кроме того, промежуточные компоненты OWIN применимы только с OWIN-совместимыми хостами, хотя эта зависимость сравнительно лучше, чем зависимость от специфического хоста/сервера вроде IIS, как в случае с HTTP-модулями. Здесь стоит обратить внимание на то, что промежуточные компоненты OWIN могут выполняться в конвейере ASP.NET (интегрированном с IIS) благодаря пакету Microsoft.Owin.Host.SystemWeb.

Обработчик сообщений Вариант расширения, предоставляемый ASP.NET Web API. Самое крупное преимущество использования обработчика сообщений для защиты в том, что это концепция инфраструктуры ASP.NET Web API и, следовательно, она не зависит от нижележащего хоста или сервера. Кроме того, обработчик сообщений выполняется только при запросах Web API. Недостаток применения обработчика сообщений — отсутствие более тонкого контроля. Обработчик можно сконфигурировать как глобальный для всех запросов или для конкретного маршрута. Для данного маршрута у вас может быть несколько контроллеров. Все эти контроллеры и содержащиеся в них методы операций должны использовать одну и ту же аутентификацию, вводимую обработчиком сообщений, который сконфигурирован для этого маршрута. Иначе говоря, минимальная гранулярность для аутентификации, реализуемой обработчиком сообщений, — это уровень маршрута.

Фильтр операции Другой вариант расширения, предлагаемый ASP.NET Web API, — фильтр операции. Однако, с точки зрения реализации аутентификации, это негодный вариант просто потому, что эти фильтры выполняются после фильтров авторизации в конвейере ASP.NET Web API. Чтобы аутентификация и авторизация работали корректно, аутентификация должна предшествовать авторизации.

Фильтр авторизации Еще один вариант расширения, предлагаемый ASP.NET Web API. Один из самых распространенных способов реализации собственной аутентификации в сценариях, требующих большей гранулярности, чем та, которая обеспечивается обработчиками сообщений. Основная проблема при использовании фильтра авторизации как для аутентификации, так и для авторизации состоит в том, что порядок выполнения фильтров авторизации не гарантируется ASP.NET Web API. Главным образом это означает, что ваш фильтр авторизации, выполняющий авторизацию, может запросто быть запущен до вашего фильтра авторизации, выполняющего аутентификацию, т. е. фильтр авторизации равно не годится для аутентификации, как и фильтр операции.

Фильтр аутентификации Это самый новый вариант расширения, доступный в ASP.NET Web API 2, и он находится в центре внимания данной статьи. Фильтры аутентификации выполняются после обработчиков сообщений, но до выполнения любых других типов фильтров. Поэтому они являются лучшим выбором для реализации обязанностей по аутентификации. Еще важнее, что фильтры аутентификации выполняются до фильтров авторизации. Используя фильтр, ориентированный либо на аутентификацию, либо на авторизацию, вы можете разделить обязанности по аутентификации и авторизации.

Более того, фильтры аутентификации обеспечивают такой уровень контроля и гранулярности, который делает их особенно полезными. Возьмем случай с Web API, спроектированной для использования как «родными» мобильными приложениями, так и AJAX-приложениями, работающими в браузере. Мобильное приложение может предоставить маркер в HTTP-заголовке Authorization, а AJAX-приложение — использовать cookie аутентификации как удостоверения.

Допустим, что некое подмножество API доступно только для «родных» мобильных приложений и что вы хотите быть уверенными в возможности доступа к методам операций только при предоставлении маркера, а не cookie (cookie уязвимы при атаке с подделкой межсайтового запроса [cross-site request forgery, XSRF], тогда как маркер в HTTP-заголовке Authorization — нет). В этом случае аутентификация должна происходить на более тонком уровне гранулярности, чем это возможно в варианте на основе хоста или даже обработчика сообщений. Фильтр аутентификации подходит для этого случая просто идеально. Вы можете применять фильтр аутентификации на основе маркера ко всем этим контроллерам или методам операций, где они должны использоваться, а фильтр аутентификации на основе cookie — в других местах. Предположим, что в этом сценарии у вас есть несколько общих методов операций и вы хотите сделать их доступными либо через маркер, либо через cookie. Вы можете просто применять фильтры аутентификации на основе как cookie, так и маркера к этим общим методам операций, и один из фильтров сможет успешно выполнить аутентификацию. Такой вид контроля — самое крупное преимущество фильтров аутентификации. Когда нужен гранулярный контроль над аутентификацией, правильный подход — реализовать обязанности по аутентификации через фильтр аутентификации, а обязанности по авторизации — через фильтр авторизации.

Стоит упомянуть здесь, что готовый фильтр аутентификации, HostAuthenticationFilter, обеспечивает аутентификацию ASP.NET Web API через промежуточные компоненты OWIN. Хотя промежуточное ПО OWIN-аутентификации выполняется в конвейере и пытается «активно» аутентифицировать входящие запросы, его также можно сконфигурировать на «пассивную» аутентификацию запросов — только по требованию. HostAuthenticationFilter позволяет запускать пассивное ПО OWIN-аутентификации по имени на более поздних стадиях конвейера Web API. Этот подход позволяет сделать код аутентификации общим для разных инфраструктур (в том числе для промежуточных компонентов OWIN-аутентификации, предоставляемых Microsoft) и в то же время поддерживает гранулярность аутентификации индивидуально для каждой операции.

Хотя аутентификацию уровня хоста можно смешивать с более гранулярной аутентификацией на основе конвейера Web API, будьте осторожны и продумайте, как аутентификация уровня хоста может повлиять на аутентификацию Web API. Например, вы могли бы разместить промежуточное ПО аутентификации на основе cookie на уровне хоста в расчете на использование с другими инфраструктурами, скажем, ASP.NET MVC, но, разрешив Web API работать с участником системы безопасности на основе cookie, вы сделаете Web API уязвимой к таким атакам, как XSRF. Чтобы помочь в таких ситуациях, метод расширения SuppressDefaultHostAuthentication позволяет Web API игнорировать любую аутентификацию, сконфигурированную на уровне хоста. Шаблон Web API по умолчанию в Visual Studio использует cookie, разрешенные на уровне хоста, и маркеры на уровне Web API. Поскольку cookie разрешены на уровне хоста и требуют предотвращения XSRF, шаблон также использует SuppressDefaultHostAuthentication, чтобы не дать конвейеру Web API работать с участником системы безопасности на основе cookie. Тем самым Web API будет использовать только участника системы безопасности на основе маркера, и вам не понадобится создавать механизмы для Web API, защищающие ее от атак XSRF.

Как заставить фильтры аутентификации и авторизации работать в тандеме

В конвейере ASP.NET Web API фильтры аутентификации выполняются первыми (только потом выполняются фильтры авторизации) по той простой причине, что авторизация зависит от установленной идентификации, которая является результатом аутентификации. Вот как можно спроектировать совместную работу фильтров аутентификации и авторизации для защиты ASP.NET Web API.

Базовый принцип этой архитектуры — на фильтр аутентификации возлагается одна и только одна обязанность проверки удостоверений, и его избавляют от любых других обязанностей. Например, фильтр аутентификации не отклонит запрос с кодом состояния 401 Unauthorized, если удостоверения не предоставлены. Он просто не определяет аутентифицированную идентификацию и откладывает вопрос о том, как обрабатывать анонимные запросы, до стадии авторизации. Фильтр аутентификации в основном осуществляет три типа операций.

  1. Если нужные удостоверения отсутствуют в запросе, фильтр ничего не делает.
  2. Если удостоверения присутствуют и распознаются как правильные, фильтр устанавливает идентификацию в форме аутентифицированного участника системы безопасности.
  3. Если удостоверения присутствуют и распознаются как неправильные, фильтр уведомляет инфраструктуру ASP.NET Web API, указывая в результате ошибку, что, по сути, приводит к возврату запрашивающему ответа «не авторизован».

Если ни один из выполняемых в конвейере фильтров аутентификации не обнаружил недопустимое удостоверение, конвейер продолжает работу, даже если аутентифицированная идентификация не установлена. Решение об обработке этого анонимного запроса возлагается на компоненты, выполняемые на более поздних стадиях конвейера.

На самом фундаментальном уровне фильтр авторизации просто проверяет, является установленная идентификация аутентифицированной. Однако фильтр авторизации может также гарантировать, что:

  • имя пользователя аутентифицированной идентификации присутствует в списке разрешенных пользователей;
  • минимум одна из ролей, сопоставленных с аутентифицированной идентификацией, есть в списке разрешенных ролей.

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

Если все фильтры авторизации «счастливы», конвейер продолжает работу, и в конечном счете метод операции API-контроллера генерирует ответ на запрос. Если идентификация не установлена или если есть несовпадение по требованиям к имени пользователя или роли, фильтр авторизации отклоняет запрос с ответом 401 Unauthorized. Рис. 1 иллюстрирует роль, выполняемую двумя фильтрами в трех сценариях: удостоверения отсутствуют, присутствуют неправильные удостоверения и имеются правильные удостоверения.

*
Увеличить

Рис. 1. Фильтры защиты в конвейере ASP.NET Web API

Credentials AbsentУдостоверений нет
Request with No CredentialЗапрос без удостоверений
No Action TakenНикаких действий не предпринимается
Rejects the Request for the Lack of Authenticated PrincipalЗапрос отклоняется из-за отсутствия аутентифицированного участника системы безопасности
Unauthorized Response with ChallengeОтвет без авторизации с запросом
Authentication FilterФильтр аутентификации
Authorization FilterФильтр авторизации
Action MethodМетод операции
Adds ChallengeДобавляет запрос
Does Not ExecuteНе выполняется
Invalid Credentials PresentПрисутствуют неправильные удостоверения
Request with Invalid CredentialЗапрос с неправильным удостоверением
context.ErrorResult Is Set to UnauthorizedResultcontext.ErrorResult присваивается UnauthorizedResult
Valid Credentials PresentПрисутствуют правильные удостоверения
Request with Valid CredentialЗапрос с правильным удостоверением
context.Principal Is Set to an Authenticated Principalcontext.Principal присваивается аутентифицированный участник системы безопасности
Successfully Authorizes, Because Identity Is AuthenticУспешно авторизуется, так как идентификация аутентична
Response MessageСообщение-ответ
No Action TakenНикаких действий не предпринимается
Action Method Runs and Produces a ResponseМетод операции выполняется и генерирует ответ

Создание фильтра аутентификации

Фильтр аутентификации — это класс, реализующий интерфейс IAuthenticationFilter. В этом интерфейсе два метода: AuthenticateAsync и ChallengeAsync:

public interface IAuthenticationFilter : IFilter
{
  Task AuthenticateAsync(HttpAuthenticationContext context, 
    CancellationToken cancellationToken);
  Task ChallengeAsync(HttpAuthenticationChallengeContext context,
    CancellationToken cancellationToken);
}

Метод AuthenticateAsync принимает HttpAuthenticationContext в качестве аргумента. Этот контекст определяет, как метод AuthenticateAsync передает результат процесса аутентификации обратно инфраструктуре ASP.NET Web API. Если сообщение-запрос содержит аутентичные удостоверения, свойству Principal переданного объекта HttpAuthenticationContext присваивается аутентифицированный участник системы безопасности. Если удостоверения неправильны, свойству ErrorResult объекта HttpAuthenticationContext присваивается UnauthorizedResult. Если в сообщении-запросе вообще нет удостоверений, метод AuthenticateAsync не предпринимает никаких действий. Код на рис. 2 демонстрирует типичную реализацию метода AuthenticateAsync, охватывающую эти три сценария. Аутентифицированным участником системы безопасности в этом примере является ClaimsPrincipal только с двумя заявками: Name и Role.

Рис. 2. Метод AuthenticateAsync

public Task AuthenticateAsync(HttpAuthenticationContext context,
  CancellationToken cancellationToken)
{
  var req = context.Request;
  // Получаем удостоверение из заголовка Authorization
  // (если есть) и выполняем аутентификацию
  if (req.Headers.Authorization != null &&
    "somescheme".Equals(req.Headers.Authorization.Scheme,
      StringComparison.OrdinalIgnoreCase))
  {
    var creds = req.Headers.Authorization.Parameter;
    if(creds == "opensesame") // заменить настоящей проверкой
    {
      var claims = new List<Claim>()
      {
        new Claim(ClaimTypes.Name, "badri"),
        new Claim(ClaimTypes.Role, "admin")
      };
      var id = new ClaimsIdentity(claims, "Token");
      var principal = new ClaimsPrincipal(new[] { id });
      // Сообщение-запрос содержит правильные удостоверенияl
      context.Principal = principal;
    }
    else
    {
      // Сообщение-запрос содержит неправильное удостоверение
      context.ErrorResult = new UnauthorizedResult(
        new AuthenticationHeaderValue[0], context.Request);
    }
  }
  return Task.FromResult(0);
}

Метод AuthenticateAsync используется для реализации основной логики аутентификации, проверяющей удостоверения в запросе, а метод ChallengeAsync — для добавления запроса аутентификации (authentication challenge). Запрос аутентификации добавляется в ответ, когда код состояния — 401 Unauthorized, и, чтобы проанализировать код состояния, вам нужен объект ответа. Но метод ChallengeAsync не позволяет анализировать ответ или устанавливать запрос (challenge) напрямую. По сути, этот метод выполняется до метода операции в ходе обработки запроса (request) в конвейере Web API. Однако параметр HttpAuthenticationChallengeContext метода ChallengeAsync дает возможность присвоить объект результата операции (IHttpActionResult) свойству Result. Метод ExecuteAsync объекта результата операции ожидает генерации ответа задачей, анализирует код состояния ответа и добавляет заголовок ответа WWWAuthenticate. Код на рис. 3 демонстрирует типичную реализацию метода ChallengeAsync. В этом примере я просто добавляю «зашитый» в код запрос аутентификации. ResultWithChallenge — это класс результата операции, созданный мной для добавления такого запроса.

Рис. 3. Метод ChallengeAsync

public Task ChallengeAsync(HttpAuthenticationChallengeContext context,
  CancellationToken cancellationToken)
{
  context.Result = new ResultWithChallenge(context.Result);
  return Task.FromResult(0);
}
public class ResultWithChallenge : IHttpActionResult
{
  private readonly IHttpActionResult next;
  public ResultWithChallenge(IHttpActionResult next)
  {
    this.next = next;
  }
  public async Task<HttpResponseMessage> ExecuteAsync(
    CancellationToken cancellationToken)
  {
    var response = await next.ExecuteAsync(cancellationToken);
    if (response.StatusCode == HttpStatusCode.Unauthorized)
    {
      response.Headers.WwwAuthenticate.Add(
        new AuthenticationHeaderValue("somescheme", "somechallenge"));
    }
    return response;
  }
}

Следующий код показывает класс фильтра:

public class TokenAuthenticationAttribute :
  Attribute, IAuthenticationFilter
{
  public bool AllowMultiple { get { return false; } }
  // Сюда помещаются методы AuthenticateAsync и ChallengeAsync
}

В дополнение к реализации интерфейса IAuthenticationFilter я наследую от Attribute, чтобы этот класс можно было применять как атрибут к уровню класса (контроллера) или метода (метода операции).

Таким образом, вы можете создать фильтр аутентификации с одной обязанностью — проверять подлинность конкретного удостоверения (в этом примере — фиктивного маркера). У фильтра аутентификации нет логики авторизации; его единственная цель — обработка аутентификации: установление идентификации, если таковая есть (при обработке сообщения запроса) и возврат запроса аутентификации, если таковой есть (в ходе обработки сообщения ответа). Фильтры авторизации обрабатывают обязанности по авторизации, например проверяют, является ли данная идентификация аутентифицированной и входит ли она в список разрешенных пользователей или ролей.

Применение фильтра авторизации

Фундаментальная цель использования фильтра авторизации — выполнение авторизации, при которой определяется, может ли пользователь получить доступ к запрошенному ресурсу. Web API предоставляет реализацию фильтра авторизации с именем AuthorizeAttribute. Применение этого фильтра гарантирует, что идентификация является аутентифицированной. Кроме того, вы можете настроить атрибут авторизации списком имен конкретных пользователей и ролей, которым разрешен доступ. Код на рис. 4 демонстрирует фильтр авторизации, применяемый на разных уровнях (глобально, на уровне контроллера и на уровне метода операции), и использует разные атрибуты идентификации для ее авторизации. В этом примере глобальный фильтр гарантирует, что идентификация аутентифицирована. Фильтр, применяемый на уровне контроллера, гарантирует, что идентификация аутентифицирована и что минимум одна роль, сопоставленная с этой идентификацией, является «admin». Фильтр, используемый на уровне метода операции, гарантирует, что что идентификация аутентифицирована и что имя пользователя — «badri». Здесь следует обратить внимание на то, что фильтр авторизации на уровне метода операции также наследует фильтры от уровня контроллера и глобального уровня. Поэтому, чтобы авторизация завершилась успешно, должны быть пройдены все фильтры: имя пользователя должно быть «badri», одна из ролей — «admin», а пользователь должен быть аутентифицирован.

Рис. 4. Применение фильтра авторизации на трех уровнях

public static class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    // Остальной конфигурационный код Web API помещается сюда
    config.Filters.Add(new AuthorizeAttribute()); // Глобальный уровень
  }
}
[Authorize(Roles="admin")] // уровень контроллера
public class EmployeesController : ApiController
{
  [Authorize(Users="badri")] // уровень метода операции
  public string Get(int id)
  {
    return “Hello World”;
  }
}

Готовый AuthorizeAttribute крайне полезен, но, если вам нужна адаптация, вы можете создать его подкласс, чтобы реализовать дополнительное поведение авторизации. Следующий код показывает собственный фильтр авторизации:

public class RequireAdminClaimAttribute : AuthorizeAttribute
{
  protected override bool IsAuthorized(HttpActionContext context)
  {
    var principal =
      context.Request.GetRequestContext().Principal as ClaimsPrincipal;
    return principal.Claims.Any(c => c.Type ==
      "http://yourschema/identity/claims/admin"
      && c.Value == "true");
  }
}

Этот фильтр просто проверяет наличие заявки «admin», но вы можете использовать участника системы безопасности и любую другую дополнительную информацию из HttpActionContext для выполнения собственной авторизации.

В первой версии ASP.NET Web API фильтры собственной авторизации зачастую ошибочно использовались для реализации аутентификации, но в случае ASP.NET Web API 2 фильтры аутентификации теперь занимают свое место в конвейере, и это помогает разработке ясного, модульного кода с четким разделением обязанностей по аутентификации и авторизации.

Переопределение фильтров

Как я уже пояснял, фильтр авторизации можно применять на трех уровнях. Указывая фильтр Authorize на глобальном уровне, вы можете ввести в действие авторизацию при вызовах всех методов операций между всеми контроллерами. Если вы хотите исключить из глобальной проверки несколько методов, то проще сделать это с помощью атрибута AllowAnonymous.

Код на рис. 5 демонстрирует применение атрибута AllowAnonymous на уровне контроллера. Хотя фильтр авторизации применен глобально, атрибут AllowAnonymous, используемый с PublicResourcesController, исключает из процесса авторизации запросы, поступающие этому контроллеру.

Рис. 5. Применение атрибута AllowAnonymous

public static class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    // Остальной конфигурационный код Web API помещается сюда
    config.Filters.Add(new AuthorizeAttribute()); // Глобальный уровень
  }
}
[AllowAnonymous]
public class PublicResourcesController : ApiController
{
  public string Get(int id)
  {
    return “Hello World”;
  }
}

AllowAnonymous предоставляет способ, которым конкретная операция может переопределять авторизацию, сконфигурированную более высокоуровневым фильтром авторизации. Однако AllowAnonymous позволяет переопределять лишь авторизацию. Допустим, вы хотите, чтобы большинство операций проверялось с использованием аутентификации HTTP Basic, но одну операцию вам нужно аутентифицировать с применением только маркеров. Было бы удобно сконфигурировать глобальную аутентификацию на основе маркеров, а потом переопределить ее для одной этой операции по аналогии с тем, как AllowAnonymous переопределяет авторизацию.

В ASP.NET Web API 2 введен новый тип фильтра специально для такого сценария — переопределяющий фильтр (override filter). В отличие от AllowAnonymous переопределяющие фильтры, появившиеся в ASP.NET Web API 2, могут работать с фильтром любого типа. Переопределяющие фильтры, как и предполагает их название, переопределяют фильтры, сконфигурированные на более высоких уровнях. Чтобы переопределить фильтры аутентификации, настроенные на более высоких уровнях, используйте готовый атрибут OverrideAuthentication. Если у вас есть фильтр аутентификации, действующий глобально, и нужно предотвратить его выполнение для конкретного метода операции или контроллера, вы может просто применить OverrideAuthentication на требуемом уровне.

Переопределяющие фильтры гораздо полезнее простого отключения конкретных фильтров. Скажем, у вас есть два фильтра аутентификации (один для аутентификации по маркеру защиты, а другой для аутентификации по паре «имя пользователя — пароль» в базовой схеме HTTP. Оба фильтра применены на глобальном уровне, делая ваш API достаточно гибким для принятия либо маркера, либо имени и пароля пользователя. В следующем коде показаны два фильтра аутентификации, примененные глобально:

public static class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    // Остальной конфигурационный код Web API помещается сюда
    config.Filters.Add(new TokenAuthenticator());
    config.Filters.Add(new HttpBasicAuthenticator(realm: "Magical"));
  }
}

Теперь, возможно, вы предпочли бы сделать так, чтобы для доступа к конкретному методу операции использовался только маркер. Чем тут может помочь OverrideAuthentication, если он просто прекращает работу всех фильтров? И здесь проявляется важная особенность переопределяющих фильтров: они отменяют все фильтры, указанные на более высоких уровнях, но не удаляют фильтры, определенные на том же уровне, что и они сами. Фактически это означает, что вы можете добавить один или более фильтров аутентификации на конкретном уровне, в то же время отключив все остальное на более высоких уровнях. Теперь вернемся к требованию использовать в качестве удостоверения только маркер для доступа к конкретному методу операции. Вы можете просто указать атрибут OverrideAuthentication и TokenAuthenticator на уровне метода операции, как показано в следующем коде (он гарантирует, что для метода операции GetAllowedForTokenOnly будет выполняться только TokenAuthenticator):

public class EmployeesController : ApiController
{
  [OverrideAuthentication] // Удаляет все фильтры аутентификации
  [TokenAuthenticator] // Возвращает только аутентификацию по маркеру
  public string GetAllowedForTokenOnly(int id)
  {
    return “Hello World”;
  }
}

Таким образом, переопределяющие фильтры, введенные в ASP.NET Web API 2, обеспечивают гораздо большую гибкость в плане глобального задания фильтров и селективной работы фильтров на более низких уровнях — только там, где нужно переопределить глобальное поведение.

В дополнение к атрибуту OverrideAuthentication существует готовый атрибут OverrideAuthorization, который удаляет фильтры авторизации, указанные на более высоких уровнях. В сравнении с AllowAnonymous отличие в том, что OverrideAuthorization удаляет только фильтры авторизации более высокого уровня. Он не удаляет фильтры авторизации, указанные на том же уровне, что и он сам. AllowAnonymous заставляет ASP.NET Web API пропускать вообще весь процесс авторизации, даже если фильтры авторизации определены на том же уровне, что и AllowAnonymous, — они просто игнорируются.

Заключение

Вы можете реализовать аутентификацию в ASP.NET Web API, используя варианты, предоставляемые хостом, а также точки расширения, предоставляемые конвейером ASP.NET Web API. Варианты на основе хоста обеспечивают тесную интеграцию с конвейером хоста и отклоняют неправильные запросы на ранних стадиях конвейера. Точки расширения ASP.NET Web API предлагают более тонкий контроль над процессом аутентификации. Когда вам требуется больший контроль над аутентификацией, использование разных механизмов аутентификации для разных контроллеров или даже методов операций, правильный подход — реализовать обязанности аутентификации через фильтр аутентификации, а обязанности авторизации через фильтр авторизации.

Автор: Бадринарайянан Лакшмирагаван  •  Иcточник: msdn.microsoft.com  •  Опубликована: 23.09.2015
Нашли ошибку в тексте? Сообщите о ней автору: выделите мышкой и нажмите CTRL + ENTER
Теги:   ASP.NET.


Оценить статью:
Вверх
Комментарии посетителей
Комментарии отключены. С вопросами по статьям обращайтесь в форум.