Как Вы обрабатываете запросы ajax, когда пользователь не аутентифицируется?

Как Вы обрабатываете запросы ajax, когда пользователь не аутентифицируется?

Кто-то вводит страницу, оставляет комнату в течение часа, возвратов, добавляет комментарий к странице, которая идет throuh ajax использование jQuery ($.post). Так как он не аутентифицируется, возврат метода результат RedirectToRoute (перенаправления к странице входа в систему). Что Вы делаете с ним? Как Вы обрабатываете его на стороне клиента и как Вы обрабатываете его в контроллере?

22
задан DaveRandom 25 February 2013 в 22:12
поделиться

4 ответа

РЕДАКТИРОВАТЬ:

Я написал выше ответ давным-давно, и теперь я считаю, что отправка 403 - неправильный путь. 403 имеет немного другое значение, и его просто не следует использовать. Это исправленный атрибут с использованием 401. Он отличается только дополнительным context.HttpContext.Response.End () в Http401Result и другим кодом HTTP:

public class OptionalAuthorizeAttribute : AuthorizeAttribute
{
    private class Http401Result : ActionResult
    {
        public override void ExecuteResult(ControllerContext context)
        {
            // Set the response code to 401.
            context.HttpContext.Response.StatusCode = 401;
            context.HttpContext.Response.Write(CTRes.AuthorizationLostPleaseLogOutAndLogInAgainToContinue);
            context.HttpContext.Response.End();
        }
    }

    private readonly bool _authorize;

    public OptionalAuthorizeAttribute()
    {
        _authorize = true;
    }

    //OptionalAuthorize is turned on on base controller class, so it has to be turned off on some controller. 
    //That is why parameter is introduced.
    public OptionalAuthorizeAttribute(bool authorize)
    {
        _authorize = authorize;
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        //When authorize parameter is set to false, not authorization should be performed.
        if (!_authorize)
            return true;

        var result = base.AuthorizeCore(httpContext);

        return result;
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
        {
            //Ajax request doesn't return to login page, it just returns 401 error.
            filterContext.Result = new Http401Result();
        }
        else
            base.HandleUnauthorizedRequest(filterContext);
    }
}

СТАРЫЙ ОТВЕТ:

Хотя мне нравятся идеи, опубликованные в другие ответы (о которых я имел представление ранее), мне нужны были образцы кода. Вот они:

Измененный атрибут авторизации:

public class OptionalAuthorizeAttribute : AuthorizeAttribute
{
    private class Http403Result : ActionResult
    {
        public override void ExecuteResult(ControllerContext context)
        {
            // Set the response code to 403.
            context.HttpContext.Response.StatusCode = 403;
            context.HttpContext.Response.Write(CTRes.AuthorizationLostPleaseLogOutAndLogInAgainToContinue);
        }
    }

    private readonly bool _authorize;

    public OptionalAuthorizeAttribute()
    {
        _authorize = true;
    }

    //OptionalAuthorize is turned on on base controller class, so it has to be turned off on some controller. 
    //That is why parameter is introduced.
    public OptionalAuthorizeAttribute(bool authorize)
    {
        _authorize = authorize;
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        //When authorize parameter is set to false, not authorization should be performed.
        if (!_authorize)
            return true;

        var result = base.AuthorizeCore(httpContext);

        return result;
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
        {
            //Ajax request doesn't return to login page, it just returns 403 error.
            filterContext.Result = new Http403Result();
        }
        else
            base.HandleUnauthorizedRequest(filterContext);
    }
}

HandleUnauthorizedRequest переопределен, поэтому он возвращает Http403Result при использовании Ajax. Http403Result изменяет StatusCode на 403 и в ответ возвращает сообщение пользователю. В атрибуте есть некоторая дополнительная логика (параметр authorize ), потому что я включаю [Authorize] в базовом контроллере и отключаю его на некоторых страницах.

Другой важной частью является глобальная обработка этого ответа на стороне клиента. Это то, что я поместил в Site.Master:

<script type="text/javascript">
    $(document).ready(
        function() {
            $("body").ajaxError(
                function(e,request) {
                    if (request.status == 403) {
                        alert(request.responseText);
                        window.location = '/Logout';
                    }
                }
            );
        }
    );
</script>

Я размещаю ГЛОБАЛЬНЫЙ обработчик ошибок ajax, и когда когда-либо $. Post завершается с ошибкой 403, появляется ответное сообщение и пользователь перенаправляется для выхода. страница. Теперь мне не нужно обрабатывать ошибку в каждом $.post запрос, потому что он обрабатывается глобально.

Почему 403, а не 401? 401 обрабатывается внутри MVC framework (поэтому перенаправление на страницу входа выполняется после неудачной авторизации).

Что вы думаете об этом?

16
ответ дан 29 November 2019 в 05:38
поделиться

Когда мой коллега спросил, как с этим справиться, я пришел к следующей идее - создать атрибут AuthorizeAjax. Он может опросить и проверить, что Request.IsAjaxRequest () и, если запрос не аутентифицирован, вернуть конкретный объект ошибки JSON. Возможно, вы можете просто переопределить атрибут AuthorizeAttribute по умолчанию и заставить его вызывать базу, если это не несанкционированный запрос AJAX, поэтому вам не нужно беспокоиться о том, помечать ли действия контроллера с помощью [Authorize] или [AuthorizeAjax].

На стороне клиента все ваши страницы должны быть оборудованы для работы с возвращенной ошибкой, но эта логика, вероятно, может использоваться совместно.

4
ответ дан 29 November 2019 в 05:38
поделиться

Я бы предложил создать свой собственный AuthorizeAttribute, и если запрос является запросом Ajax , выбросить исключение HttpException (401/403). А также переключитесь на использование метода Ajax в jQuery .

Предполагая, что вы реализовали страницы ошибок и они возвращают правильный код состояния, будет выполнен обратный вызов error вместо обратного вызова success . Это произойдет из-за кода ответа.

2
ответ дан 29 November 2019 в 05:38
поделиться

Самым простым и чистым решением, которое я нашел для этого, является регистрация обратного вызова с событием jQuery.ajaxSuccess () и проверка заголовка ответа «X-AspNetMvc-Version».

Каждый запрос jQuery Ajax в моем приложении обрабатывается Mvc, поэтому, если заголовок отсутствует, я знаю, что мой запрос был перенаправлен на страницу входа, и я просто перезагружаю страницу для перенаправления верхнего уровня:

 $(document).ajaxSuccess(function(event, XMLHttpRequest, ajaxOptions) {
    // if request returns non MVC page reload because this means the user 
    // session has expired
    var mvcHeaderName = "X-AspNetMvc-Version";
    var mvcHeaderValue = XMLHttpRequest.getResponseHeader(mvcHeaderName);

    if (!mvcHeaderValue) {
        location.reload();
    }
});

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

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

0
ответ дан 29 November 2019 в 05:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: