Когда он был впервые разработан, System.Web.Mvc.AuthorizeAttribute действовал правильно - более ранние версии спецификации HTTP использовали код состояния 401 как для «неавторизованного», так и «неаутентифицированного».
Из оригинальной спецификации:
Если в запрос уже включены учетные данные авторизации, то ответ 401 указывает, что в авторизации было отказано для этих учетных данных.
На самом деле, вы можете увидеть путаницу прямо здесь - она использует слово «авторизация», когда оно означает «аутентификация». Однако в повседневной практике имеет смысл возвращать 403 Запрещено, когда пользователь аутентифицирован, но не авторизован. Маловероятно, что у пользователя будет второй набор учетных данных, который предоставит ему доступ - плохой пользовательский опыт со всех сторон.
Рассмотрим большинство операционных систем - когда вы пытаетесь прочитать файл, к которому у вас нет прав доступа, вам не показывается экран входа!
К счастью, спецификации HTTP были обновлены (июнь 2014 г.), чтобы устранить неоднозначность.
Из «Гипертекстового транспортного протокола (HTTP / 1.1): аутентификация» (RFC 7235):
Код состояния 401 (неавторизованный) указывает, что запрос не был применен, поскольку в нем отсутствуют действительные учетные данные аутентификации для целевого ресурса.
Из «Протокола передачи гипертекста (HTTP / 1.1): семантика и контент» (RFC 7231):
Код состояния 403 (Запрещено) указывает, что сервер понял запрос, но отказывается его авторизовать.
Интересно, что на момент выпуска ASP.NET MVC 1 поведение AuthorizeAttribute было правильным. Теперь поведение некорректно - спецификация HTTP / 1.1 была исправлена.
Вместо того, чтобы пытаться изменить перенаправления страницы входа в ASP.NET, проще просто устранить проблему у источника. Вы можете создать новый атрибут с таким же именем ( 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);
}
}
}