Как перехватить 401 от проверки подлинности с помощью форм в ASP.NET MVC? - PullRequest
14 голосов
/ 28 мая 2010

Я хотел бы создать страницу 401, если у пользователя нет необходимых прав.

Пользователь запрашивает URL-адрес и перенаправляется на страницу входа (я запретил анонимные действия в web.config). Пользователь успешно входит в систему и перенаправляется на исходный URL. Однако при проверке разрешений определяется, что у пользователя нет необходимых разрешений, поэтому я хотел бы сгенерировать 401. Но проверка подлинности с помощью форм всегда обрабатывает 401 и перенаправляет пользователя на страницу входа.

Для меня это не правильно. Пользователь уже аутентифицирован , у пользователя просто нет правильной авторизации .

В других сценариях, например в сценарии службы ajax или REST, я определенно не хочу страницу входа - мне нужна правильная страница 401.

До сих пор я пробовал собственный фильтр авторизации для возврата ViewResult с 401, но не работал. Затем я попробовал обычный фильтр действий, переопределяющий 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.

Ответы [ 4 ]

8 голосов
/ 29 мая 2010

Я нашел работоспособное решение.

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 не волнует.

6 голосов
/ 10 февраля 2014
HttpContext.Current.Response.SuppressFormsAuthenticationRedirect = true;
2 голосов
/ 29 мая 2010

Я согласен, что поведение по умолчанию неверно, особенно с учетом запросов Ajax. Я надеюсь увидеть какое-то решение в MVCv3 (скрестив пальцы).

Единственный способ, которым я знаю, - это удалить раздел Authentication в web.config, это то, что ASP.NET ищет для перенаправления неавторизованных запросов. Вы не можете отключить эту "функцию", насколько мне известно. Если у вас есть раздел аутентификации, вы будете перенаправлены на URL-адрес входа, если ASP.NET когда-либо обнаружит код состояния 401.

Но, удалив это, у вас есть другие проблемы. Если вы когда-нибудь захотите, чтобы пользователь перенаправлялся на страницу входа для запросов, не являющихся AJAX, вам нужно будет реализовать свой собственный AuthorizeAttribute и использовать пользовательские настройки, чтобы определить, куда перенаправлять. Кроме того, все остальное в разделе «Аутентификация», вероятно, также должно быть реализовано вами. Не очень практичное решение для сложных сайтов.

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

0 голосов
/ 28 мая 2010

Возможно, вы захотите посмотреть здесь: Пользовательская обработка ошибок ASP.NET MVC Application_Error Global.asax?

Вы должны быть в состоянии поймать 401 и направить к пользовательскому действию в этой точке. Мы делаем это для 404 и других исключений в нашем коде, и это работает довольно хорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...