Несанкционированный результат в запросах ajax

У меня есть приложение со многими действиями ajax (реализовано с использованием JQuery.ajax), которое возвращает JSON ot html. Некоторые из них должны быть доступны только авторизованным пользователям, и я украсил их атрибутом [Authorize]. Для не ajax-действий, если пользователь не авторизован - система перенаправляет его на страницу входа (которая настроена в web.config).

Но это не применимо для действий ajax, потому что если пользователь был авторизован - он загружает страницу, после того, как cookie истекает, и он не авторизовался, а вместо html-блока, который должен заменить старый, он получает мою страницу входа в блок,

Я знаю, что я могу решить эту проблему вручную, например, удалить атрибут [Авторизовать] и вернуть специальный json/empty html, если пользователь не авторизован. Но мне не нравится это решение, потому что мне нужно переписать все мои действия и функции ajax. Я хочу глобальное решение, которое позволяет мне не переписывать мои действия (может быть настраиваемый атрибут авторизации или какая-то некорректная обработка неавторизованного результата).

Я хочу вернуть код состояния, если запрос является ajax и перенаправляется на страницу входа, если запрос не является ajax.

Ответы

Ответ 1

Добавьте обработчик Application_EndRequest к вашему коду в файле global.asax.cs, который изменяет любую ошибку 302 (перенаправление на страницу входа) на ошибку 401 (несанкционированная) для запроса AJAX. Это позволит вам просто оставить действия вашего контроллера такими, какие они есть, и обработать перенаправление (вы действительно можете иметь только регистрацию пользователя, если они не находятся на данный момент) через клиента.

protected void Application_EndRequest()
{
    // Any AJAX request that ends in a redirect should get mapped to an unauthorized request
    // since it should only happen when the request is not authorized and gets automatically
    // redirected to the login page.
    var context = new HttpContextWrapper( Context );
    if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest())
    {
        context.Response.Clear();
        Context.Response.StatusCode = 401;
    }
}

Затем в файле _Layout.cshtml добавьте глобальный обработчик ошибок AJAX, который перенаправляет ваше действие для входа, когда он получает ответ 401.

<script type="text/javascript">
    $(function () {
        $(document).ajaxError(function (e, xhr, settings) {
            if (xhr.status == 401) {
                location = '@Url.Action( "login", "account" )';
            }
        });
    });
</script>

Вы также можете попробовать некоторые из методов, описанных в блоге Фила Хаака, Предотвратить повторную регистрацию страницы авторизации формы, когда вы этого не хотите

Ответ 2

Вам не нужно переписывать все ваши действия, просто создайте собственный фильтр, чтобы заменить встроенный фильтр Authorize.

Другие люди сделали это раньше

asp.net mvc [handleerror] [авторизовать] с JsonResult?

Ответ 3

Вы можете проверить метод расширения Request.IsAjaxRequest() и выполнить определенное действие, если оно истинно.

Ответ 4

Возможно, ваше действие LogOn в вашем AccountController (или везде, где у вас есть) может вернуть другой результат, если Request.IsAjaxRequest() - true.

Это означает, что если вызов AJAX авторизованного действия не разрешает авторизацию, вы должны иметь возможность вернуть соответствующий ответ с помощью действия LogOn.

например.

public ActionResult LogOn()
{
    if (Request.IsAjaxRequest())
    {
        // do appropriate response for ajax call here
    }

    return View();
}

Затем вам не нужно делать основной переписывать