Почему AuthorizeAttribute перенаправляет на страницу входа для сбоев проверки подлинности и авторизации?



In ASP.NET MVC, вы можете пометить метод контроллера с помощью AuthorizeAttribute, например:



[Authorize(Roles = "CanDeleteTags")]
public void Delete(string tagName)
{
// ...
}


это означает, что, если текущий вошедший в систему пользователь не находится в роли "CanDeleteTags", метод контроллера никогда не будет вызван.



к сожалению, для сбоев, AuthorizeAttribute возвращает HttpUnauthorizedResult, который всегда возвращает код состояния HTTP 401. Это вызывает перенаправление на страницу входа.



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



кажется,AuthorizeAttribute результате проверки подлинности и авторизации.



это кажется немного оплошностью в ASP.NET MVC, или я что-то упустил?



мне пришлось готовить DemandRoleAttribute это разделяет два. Когда пользователь не проходит проверку подлинности, он возвращает HTTP 401, отправляя их на страницу входа. Когда пользователь вошел в систему, но не в требуемой роли, он создает . В настоящее время перенаправляет на страницу ошибки.



конечно, я не должен этого делать?

684   6  

6 ответов:

когда он был впервые разработан, система.Сеть.Mvc.AuthorizeAttribute делал правильные вещи - более старые версии спецификации HTTP использовали код состояния 401 как для "несанкционированного", так и для "неавторизованного".

из исходной спецификации:

Если запрос уже включал учетные данные авторизации, то ответ 401 указывает, что авторизация была отклонена для этих учетных данных.

в самом деле, вы можете увидеть путаница тут же-он использует слово "авторизация", когда оно означает"аутентификация". Однако в повседневной практике имеет смысл возвращать 403 запрещенный, когда пользователь аутентифицирован, но не авторизован. Маловероятно, что у пользователя будет второй набор учетных данных, который даст им доступ - плохой пользовательский опыт вокруг.

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

к счастью, спецификации HTTP были обновлены (июнь 2014), чтобы устранить двусмысленность.

из "Hyper Text Transport Protocol (HTTP / 1.1): Authentication" (RFC 7235):

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

из "протокола передачи гипертекста (HTTP / 1.1): семантика и содержание" (RFC 7231):

код состояния 403 (запрещено) указывает, что сервер понял запрос, но отказывается авторизовать его.

интересно, в то время ASP.NET MVC 1 был выпущен поведение AuthorizeAttribute было правильным. Теперь поведение неверно-спецификация HTTP / 1.1 была исправлена.

вместо того, чтобы пытаться изменить ASP.NET ' s страница входа перенаправляет, это проще просто исправить проблему в источнике. Вы можете создать новый атрибут с тем же именем (AuthorizeAttribute)в пространстве имен по умолчанию вашего сайта (это очень важно), то компилятор автоматически заберет его вместо стандартного MVC. Конечно, вы всегда можете дать атрибуту новое имя, если вы предпочитаете такой подход.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

добавьте это в свой логин Page_Load функции:

// User was redirected here because of authorization section
if (User.Identity != null && User.Identity.IsAuthenticated)
    Response.Redirect("Unauthorized.aspx");

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

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

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

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

http://www.codeproject.com/KB/aspnet/Custon401Page.aspx

(Это не относится к MVC)

Я думаю, что в большинстве случаев лучшим решением является ограничение доступа к несанкционированным ресурсам до того, как пользователь попытается туда попасть. Удалив / посерев ссылку или кнопку, которая может их принять на эту несанкционированную страницу.

вероятно, было бы неплохо иметь дополнительный параметр в атрибуте, чтобы указать, куда перенаправлять несанкционированного пользователя. Но пока я смотрю на AuthorizeAttribute как на страховочную сетку.

попробуйте это в вашем обработчике Application_EndRequest вашего глобального.файл ascx

if (HttpContext.Current.Response.Status.StartsWith("302") && HttpContext.Current.Request.Url.ToString().Contains("/<restricted_path>/"))
{
    HttpContext.Current.Response.ClearContent();
    Response.Redirect("~/AccessDenied.aspx");
}

Если вы используете aspnetcore 2.0, используйте это:

using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace Core
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class AuthorizeApiAttribute : Microsoft.AspNetCore.Authorization.AuthorizeAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            var user = context.HttpContext.User;

            if (!user.Identity.IsAuthenticated)
            {
                context.Result = new UnauthorizedResult();
                return;
            }
        }
    }
}

Comments

    Ничего не найдено.