Как перехватить 401 из проверки подлинности форм в ASP.NET MVC?
Я хотел бы создать страницу 401, если у пользователя нет правильного разрешения.
Пользователь запрашивает URL-адрес и перенаправляется на страницу входа (я запрещаю анонимность в web.config). Пользователь регистрируется успешно и перенаправляется на исходный URL-адрес. Тем не менее, при проверке разрешения определяется, что у пользователя нет необходимого разрешения, поэтому я хотел бы сгенерировать 401. Но проверка подлинности по формам всегда обрабатывает 401 и перенаправляет пользователя на страницу входа.
Для меня это неверно. Пользователь уже аутентифицирован, пользователь просто не имеет правильной авторизации.
В других сценариях, например, в сценарии службы ajax или REST, я определенно не хочу страницу входа в систему - мне нужна страница 401.
До сих пор я пробовал настраиваемый фильтр Authorize для возврата ViewResult с 401, но не работал. Затем я попробовал обычный Action Filter, переопределяющий OnActionExecuting, который тоже не работал.
Что мне удалось сделать, это обработать событие в global.asax, PostRequestHandlerExecute и проверить разрешение, а затем выписать непосредственно ответ:
if (permissionDenied)
{
Context.Response.StatusCode = 401;
Context.Response.Clear();
Context.Response.Write("Permission Denied");
Context.Response.Flush();
Context.Response.Close();
return;
}
Это работает, но это не совсем то, что я хочу.
Прежде всего, я даже не уверен, что это подходящее событие или место в этом процессе.
Во-вторых, я хочу, чтобы страница 401 имела немного больше контента. Предпочтительно, это должна быть страница aspx с, возможно, той же главной страницей, что и остальная часть сайта. Таким образом, любой, кто просматривает сайт, может видеть, что разрешение отклонено, но с тем же внешним видом и т.д., Но пользователь ajax или службы получит соответствующий код состояния, чтобы действовать.
Любая идея, как это можно достичь?
Я видел другие сообщения с похожими запросами, но не видел решения, которые я могу использовать.
И нет, я не хочу 403.
Ответы
Ответ 1
Я нашел работоспособное решение.
401 перенаправление с помощью FormsAuthenticationModule происходит во время EndRequest. Поскольку во время обработки событий модули вызывается перед global.asax, мы можем переопределить код состояния после того, как FormsAuthenticationModule имеет свои грязные руки в запросе.
В моем настраиваемом AuthorizationFilter я установил HttpContext.Items [ "PermissionDenied" ] в true, а затем в мой global.asax EndRequest, я переворачиваю код состояния от 200 до 401. Затем я Server.Transfer к своему пользовательскому представлению PermissionDenied.
Я бы предпочел, чтобы сам FormsAuthenticationModule был обновлен, чтобы справиться с этим сценарием, но я думаю, что это не слишком хаки, что я думаю, что смогу жить с ним.
Очевидно, вы можете изменить, как вы сигнализируете, что global.asax должен перевернуть код состояния. Я просто попытался установить код состояния на что-то вроде 511 и использовал это как условие, а не HttpContext.Items, и это сработало. Я догадываюсь, что до сих пор правильный код состояния выходит за дверь, движок ASP.NET не волнует.
Ответ 2
HttpContext.Current.Response.SuppressFormsAuthenticationRedirect = true;
Ответ 3
Я согласен, что поведение по умолчанию неверно, особенно учитывая запросы Ajax. Я надеюсь увидеть какое-то решение в MVCv3 (скрещенные пальцы).
Единственный способ, которым я это знаю, - удалить раздел "Аутентификация" в файле web.config, это то, что ASP.NET ищет для перенаправления несанкционированных запросов. Насколько мне известно, эту функцию нельзя отключить. Если у вас есть раздел аутентификации, вы будете перенаправлены на URL-адрес входа, если ASP.NET когда-либо встретит код состояния 401
.
Но, удалив это, у вас есть другие проблемы. Если вы хотите, чтобы пользователь был перенаправлен на страницу входа в систему для неадлайновых запросов, вам нужно будет реализовать свой собственный AuthorizeAttribute
и использовать пользовательские настройки, чтобы определить, куда перенаправить. Кроме того, что-либо еще в разделе "Аутентификация", вероятно, придется повторно выполнить и вы. Не очень практичное решение в сложных местах.
Я не сделал этого сам, я решил вернуться вместо 403
. Это раздражает отсутствие верного HttpCode, но это лучше, чем любое другое решение, которое я нашел до сих пор.
Ответ 4
Вы можете посмотреть здесь: ASP.NET MVC Пользовательская обработка ошибок Application_Error Global.asax?
Вы должны уловить 401 и перейти к пользовательскому действию в этой точке. Мы делаем это для 404 и других исключений в нашем коде, и он работает очень хорошо.