Фильтры авторизации

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core

Последнее обновление: 29.10.2015

Фильтры авторизации ограничивают доступ к методам контроллера для определенных пользователей. Однако не стоит их путать с ранее описанными фильтрами аутентификации. Цель фильтров аутентификации - определить, что это за пользователь. А цель фильтров авторизации - определение прав аутентифицированного пользователя в системе.

Все фильтры авторизации реализуют интерфейс IAuthorizationFilter, который расположен в пространстве имен System.Web.Http.Filters:

public interface IAuthorizationFilter : IFilter 
{
	Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, 
					CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation);
}

Логика авторизации может быть реализована самыми разными способами. Но наиболее распространенный подход заключается в получении данных из объекта HttpRequestContext.Principal. И если данные запроса не удовлетворяют некоторым условиям, то клиенту возвращается статусный код 401 (Unauthorized).

Итак, создадим свой фильтр авторизации:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;

namespace WebApiApp.Filters
{
    public class CustomAuthorizationAttribute : Attribute, IAuthorizationFilter
    {
        private string[] usersList;
        public CustomAuthorizationAttribute(params string[] users) 
        {
            this.usersList = users;
        }
        public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext,
                        CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) 
        {
            IPrincipal principal = actionContext.RequestContext.Principal;
            if (principal == null || !usersList.Contains(principal.Identity.Name) )
            {
                return Task.FromResult<HttpResponseMessage>(
                       actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized));
            } 
            else 
            {
                return continuation();
            }
        }
        public bool AllowMultiple 
        {
            get { return false; }
        }
    }
}

Данный фильтр очень примитивен: он будет смотреть, входит ли логин пользователя в определенный набор логинов, которым разрешен доступ к ресурсу. В методе ExecuteAuthorizationFilterAsync() мы получаем из контекста объект IPrincipal, который содержит данные о ранее аутентифицированном пользователе.

Если IPrincipal не определен или логин пользователя не входит в число разрешенных, то посылается статусный код Unauthorized. Если же все условия соблюдены, то выполняем метод, к которому применяется атрибут. Для этого вызывается делегат continuation, который собственно и предоставляет выполняемый метод.

Применение фильтра:

[CustomAuthorization("eugene")]
public string Get(int id)
{
    return "Login: " + User.Identity.Name;
}

Надо учитывать, что аутентификация пользователя и создание объекта IPrincipal происходит в фильтре аутентификации, и к моменту авторизации IPrincipal в случае удачной аутентификации должен нести данные о логине пользователя. А в фильтре авторизации указываем набор логинов, которым разрешен доступ.

В большинстве случаев нет необходимости создавать свои механизмы авторизации, так как Web API имеет встроенную реализацию данного фильтра в виде атрибута Authorize. Он имеет два свойства Users и Roles, которые позволяют указать соответственно набор логинов и ролей, для которых разрешен доступ:

[Authorize(Roles = "admins,users", Users="sergey,eugene")]
public string Get(int id)
{
    return "Login: " + User.Identity.Name;
}

Если мы хотим применить несколько ролей или логинов, то они разделяются запятой. В данном случае доступ к методу Get имеют все пользователи, входящие в группы admins и users, и те, которые имеют логины sergey и eugene.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850