Коли вона була вперше розроблена, 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);
}
}
}