Как управлять запросом на перенаправление после вызова jQuery Ajax

Я использую $.post() для вызова сервлета с использованием Ajax, а затем использую полученный фрагмент HTML для замены элемента div на текущей странице пользователя. Однако, если время сеанса истекло, сервер отправляет директиву перенаправления, чтобы отправить пользователя на страницу входа. В этом случае jQuery заменяет элемент div содержимым страницы входа в систему, заставляя пользователя увидеть действительно редкую сцену.

Как я могу управлять директивой перенаправления из вызова Ajax с помощью jQuery 1. 2. 6?

вопрос задан 13.10.2008
Elliot Vargas
8553 репутация

31 ответов


  • 637 рейтинг

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

    После более долгих поисков я отказался от этого подхода и использовал JSON . В этом случае все ответы на ajax-запросы имеют код состояния 200, а тело ответа содержит объект JSON, созданный на сервере. Затем JavaScript на клиенте может использовать объект JSON, чтобы решить, что ему нужно делать.

    У меня была похожая проблема с твоей. Я выполняю ajax-запрос, который имеет 2 возможных ответа: один перенаправляет браузер на новую страницу, а другой заменяет существующую HTML-форму на текущей странице новой. Код jquery для этого выглядит примерно так:

    $.ajax({
        type: "POST",
        url: reqUrl,
        data: reqBody,
        dataType: "json",
        success: function(data, textStatus) {
            if (data.redirect) {
                // data.redirect contains the string URL to redirect to
                window.location.href = data.redirect;
            }
            else {
                // data.form contains the HTML for the replacement form
                $("#myform").replaceWith(data.form);
            }
        }
    });
    

    Объект JSON «данные» создается на сервере, чтобы иметь 2 члена: данные. перенаправление и данные. форма. Я нашел этот подход гораздо лучше.

    ответ дан Steg, с репутацией 7997, 7.10.2009
  • 216 рейтинг

    Я решил эту проблему:

    1. Добавление пользовательского заголовка в ответ:

      public ActionResult Index(){
          if (!HttpContext.User.Identity.IsAuthenticated)
          {
              HttpContext.Response.AddHeader("REQUIRES_AUTH","1");
          }
          return View();
      }
      
    2. Привязка функции JavaScript к событию ajaxSuccess и проверка наличия заголовка:

      $(document).ajaxSuccess(function(event, request, settings) {
          if (request.getResponseHeader('REQUIRES_AUTH') === '1') {
             window.location = '/';
          }
      });
      
    ответ дан Elliot Vargas, с репутацией 8553, 23.02.2009
  • 108 рейтинг

    Ни один браузер не обрабатывает правильно ответы 301 и 302. И на самом деле в стандарте даже говорится, что они должны обращаться с ними «прозрачно», что является огромной головной болью для поставщиков Ajax Library. В Ra-Ajax мы были вынуждены использовать код состояния HTTP-ответа 278 (просто некоторый «неиспользуемый» код успеха) для прозрачной обработки перенаправлений с сервера. , ,

    Это действительно раздражает меня, и если у кого-то здесь есть некоторая «тяга» в W3C, я был бы признателен, чтобы вы позволили W3C знать , что нам действительно нужно обрабатывать коды 301 и 302 самостоятельно. , , ! ;)

    ответ дан Thomas Hansen, с репутацией 4373, 20.11.2008
  • 87 рейтинг

    Решение, которое в конечном итоге было реализовано, состояло в том, чтобы использовать оболочку для функции обратного вызова вызова Ajax и в этой оболочке проверять наличие определенного элемента в возвращенном фрагменте HTML. Если элемент был найден, то оболочка выполняет перенаправление. Если нет, то оболочка перенаправила вызов в функцию фактического обратного вызова.

    Например, наша функция-обертка была что-то вроде:

    function cbWrapper(data, funct){
        if($("#myForm", data).length > 0)
            top.location.href="login.htm";//redirection
        else
            funct(data);
    }
    

    Затем при вызове Ajax мы использовали что-то вроде:

    $.post("myAjaxHandler", 
           {
            param1: foo,
            param2: bar
           },
           function(data){
               cbWrapper(data, myActualCB);
           }, 
           "html"
    );
    

    Это сработало для нас, потому что все вызовы Ajax всегда возвращали HTML внутри элемента DIV, который мы используем для замены части страницы. Также нам нужно было только перенаправить на страницу входа.

    ответ дан Elliot Vargas, с репутацией 8553, 27.01.2009
  • 60 рейтинг

    Мне нравится метод Тиммерца с легким поворотом лимона. Если вам когда-либо будет возвращено contentType из text / html , когда вы ожидаете JSON , вы, скорее всего, будете перенаправлены. В моем случае я просто перезагружаю страницу, и она перенаправляется на страницу входа. О, и проверьте, что статус jqXHR равен 200, что кажется глупым, потому что вы находитесь в функции ошибок, верно? В противном случае допустимые ошибки приводят к повторной загрузке (упс)

    $.ajax(
       error:  function (jqXHR, timeout, message) {
        var contentType = jqXHR.getResponseHeader("Content-Type");
        if (jqXHR.status === 200 && contentType.toLowerCase().indexOf("text/html") >= 0) {
            // assume that our login has expired - reload our current page
            window.location.reload();
        }
    
    });
    
    ответ дан BrianY, с репутацией 601, 23.08.2011
  • 46 рейтинг

    Используйте низкоуровневый вызов $.ajax():

    $.ajax({
      url: "/yourservlet",
      data: { },
      complete: function(xmlHttp) {
        // xmlHttp is a XMLHttpRquest object
        alert(xmlHttp.status);
      }
    });
    

    Попробуйте это для перенаправления:

    if (xmlHttp.code != 200) {
      top.location.href = '/some/other/page';
    }
    
    ответ дан Till, с репутацией 19741, 13.10.2008
  • 32 рейтинг

    Я просто хотел поделиться своим подходом, так как это может кому-то помочь:

    Я в основном включил модуль JavaScript, который обрабатывает аутентификационные вещи, такие как отображение имени пользователя, а также этот случай, обрабатывающий перенаправление на страницу входа .

    Мой сценарий: у нас в основном ISA-сервер, который прослушивает все запросы, а отвечает 302 и заголовком расположения на нашу страницу входа.

    В моем модуле JavaScript мой начальный подход был что-то вроде

    $(document).ajaxComplete(function(e, xhr, settings){
        if(xhr.status === 302){
            //check for location header and redirect...
        }
    });
    

    Проблема (как многие здесь уже упоминали) заключается в том, что браузер обрабатывает перенаправление самостоятельно, поэтому мой обратный вызов ajaxComplete никогда не вызывался, но вместо этого я получил ответ уже перенаправленной страницы входа , который, очевидно, был status 200. Проблема: как вы определяете, является ли успешный ответ 200 вашей действительной страницей входа или просто какой-то другой произвольной страницей? ?

    Решение

    Так как я не смог перехватить 302 ответа на перенаправление, я добавил заголовок LoginPage на свою страницу входа, который содержал URL самой страницы входа. В модуле я сейчас слушаю заголовок и делаю редирект:

    if(xhr.status === 200){
        var loginPageRedirectHeader = xhr.getResponseHeader("LoginPage");
        if(loginPageRedirectHeader && loginPageRedirectHeader !== ""){
            window.location.replace(loginPageRedirectHeader);
        }
    }
    

    . , , и это работает как шарм :). Вы можете удивиться, почему я включил URL в заголовок LoginPage. , , ну, в основном, потому что я не нашел способа определить URL GET в результате автоматического перенаправления местоположения из объекта xhr. , ,

    ответ дан Juri, с репутацией 21573, 23.05.2012
  • 28 рейтинг

    Я знаю, что эта тема старая, но я дам еще один подход, который я нашел и ранее описал здесь 685719079 . В основном я использую ASP. MVC с WIF (но это не очень важно для контекста этой темы - ответ адекватен, независимо от того, какие платформы используются. Подсказка остается неизменной - решение проблем, связанных с ошибками аутентификации при выполнении запросов AJAX) .

    Подход, показанный ниже, может применяться ко всем Ajax-запросам из коробки (если они явно не переопределяют событие beforeSend).

    $.ajaxSetup({
        beforeSend: checkPulse,
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            document.open();
            document.write(XMLHttpRequest.responseText);
            document.close();
        }
    });
    

    Перед выполнением любого запроса ajax вызывается метод CheckPulse (метод контроллера, который может быть простым):

    [Authorize]
    public virtual void CheckPulse() {}
    

    Если пользователь не аутентифицирован (токен истек), такой метод недоступен (защищен атрибутом Authorize). Поскольку инфраструктура обрабатывает аутентификацию, а срок действия токена истекает, она добавляет http-статус 302 в ответ. Если вы не хотите, чтобы ваш браузер обрабатывал отклик 302 прозрачно, перехватите его в Global. asax и измените статус ответа - например, на 200 OK. Кроме того, добавьте заголовок, который инструктирует вас обрабатывать такой ответ особым образом (позже на стороне клиента):

    protected void Application_EndRequest()
    {
        if (Context.Response.StatusCode == 302
            && (new HttpContextWrapper(Context)).Request.IsAjaxRequest())
        {                
            Context.Response.StatusCode = 200;
            Context.Response.AddHeader("REQUIRES_AUTH", "1");
        }
    }
    

    Наконец, на стороне клиента проверьте наличие такого настраиваемого заголовка. Если присутствует - полное перенаправление на страницу входа в систему (в моем случае window.location заменяется на URL из запроса, который обрабатывается моей платформой автоматически).

    function checkPulse(XMLHttpRequest) {
        var location = window.location.href;
        $.ajax({
            url: "/Controller/CheckPulse",
            type: 'GET',
            async: false,
            beforeSend: null,
            success:
                function (result, textStatus, xhr) {
                    if (xhr.getResponseHeader('REQUIRES_AUTH') === '1') {
                        XMLHttpRequest.abort(); // terminate further ajax execution
                        window.location = location;
                    }
                }
        });
    }
    
    ответ дан jwaliszko, с репутацией 11442, 6.05.2013
  • 22 рейтинг

    Я думаю, что лучший способ справиться с этим - использовать существующие коды ответов протокола HTTP, в частности 401 Unauthorized.

    Вот как я это решил:

    1. Сторона сервера: если сеанс истекает, а запрос является ajax. отправить заголовок кода ответа 401
    2. Клиентская часть: привязка к событиям ajax

      $('body').bind('ajaxSuccess',function(event,request,settings){
      if (401 == request.status){
          window.location = '/users/login';
      }
      }).bind('ajaxError',function(event,request,settings){
      if (401 == request.status){
          window.location = '/users/login';
      }
      });
      

    IMO, это более общий термин, и вы не пишете какую-то новую пользовательскую спецификацию / заголовок. Вам также не нужно изменять какие-либо из ваших существующих вызовов ajax.

    Редактировать: Согласно приведенному ниже комментарию @ Роба, 401 (код состояния HTTP для ошибок аутентификации) должен быть индикатором. См. 403 Forbidden vs 401 Unauthorized HTTP response для более подробной информации. При этом некоторые веб-фреймворки используют 403 как для аутентификации, так и для ошибок авторизации - поэтому адаптируйтесь соответственно. Спасибо, Роб.

    ответ дан rynop, с репутацией 21766, 23.10.2012
  • 20 рейтинг

    Я решил эту проблему следующим образом:

    Добавьте промежуточное программное обеспечение для обработки ответа, если это перенаправление для запроса ajax, измените ответ на обычный ответ с URL-адресом перенаправления.

    class AjaxRedirect(object):
      def process_response(self, request, response):
        if request.is_ajax():
          if type(response) == HttpResponseRedirect:
            r = HttpResponse(json.dumps({'redirect': response['Location']}))
            return r
        return response
    

    Тогда в ajaxComplete, если ответ содержит перенаправление, он должен быть перенаправлением, поэтому измените местоположение браузера.

    $('body').ajaxComplete(function (e, xhr, settings) {
       if (xhr.status == 200) {
           var redirect = null;
           try {
               redirect = $.parseJSON(xhr.responseText).redirect;
               if (redirect) {
                   window.location.href = redirect.replace(/\?.*$/, "?next=" + window.location.pathname);
               }
           } catch (e) {
               return;
           }
       }
    }
    
    ответ дан Tyr, с репутацией 624, 6.01.2012
  • 17 рейтинг

    Другое решение, которое я нашел (особенно полезно, если вы хотите установить глобальное поведение), заключается в использовании метода $.ajaxsetup() вместе со свойством statusCode . Как указали другие, не используйте код состояния перенаправления (3xx), вместо этого используйте код состояния 4xx и обрабатывайте перенаправление на стороне клиента.

    $.ajaxSetup({ 
      statusCode : {
        400 : function () {
          window.location = "/";
        }
      }
    });
    

    Замените 400 на код состояния, который вы хотите обработать. Как уже упоминалось, 401 Unauthorized может быть хорошей идеей. Я использую 400, поскольку он очень неопределенный, и я могу использовать 401 для более конкретных случаев (например, неправильные учетные данные для входа). Таким образом, вместо прямого перенаправления ваш сервер должен вернуть код ошибки 4xx по истечении времени сеанса, и вы обрабатываете перенаправление на стороне клиента. Прекрасно работает для меня даже с такими фреймворками, как магистраль. JS

    ответ дан morten.c, с репутацией 2565, 1.05.2014
  • 17 рейтинг

    Большинство данных решений используют обходной путь, используя дополнительный заголовок или неправильный HTTP-код. Эти решения, скорее всего, будут работать, но чувствуют себя немного «хакерами». Я придумал другое решение.

    Мы используем WIF, который настроен на перенаправление (passiveRedirectEnabled = "true") на ответ 401. Перенаправление полезно при обработке обычных запросов, но не будет работать для запросов AJAX (поскольку браузеры не будут выполнять редирект 302 /).

    Используя следующий код в вашем глобальном. asax вы можете отключить перенаправление для запросов AJAX:

        void WSFederationAuthenticationModule_AuthorizationFailed(object sender, AuthorizationFailedEventArgs e)
        {
            string requestedWithHeader = HttpContext.Current.Request.Headers["X-Requested-With"];
    
            if (!string.IsNullOrEmpty(requestedWithHeader) && requestedWithHeader.Equals("XMLHttpRequest", StringComparison.OrdinalIgnoreCase))
            {
                e.RedirectToIdentityProvider = false;
            }
        }
    

    Это позволяет вам возвращать 401 ответ на запросы AJAX, которые ваш javascript может затем обработать, перезагрузив страницу. При перезагрузке страницы выдается 401, который будет обрабатываться WIFE (и WIFE перенаправит пользователя на страницу входа).

    Пример Javascript для обработки 401 ошибок:

    $(document).ajaxError(function (event, jqxhr, settings, exception) {
    
        if (jqxhr.status == 401) { //Forbidden, go to login
            //Use a reload, WIF will redirect to Login
            location.reload(true);
        }
    });
    
    ответ дан Rob, с репутацией 1348, 14.02.2014
  • 17 рейтинг

    Эта проблема может возникнуть при использовании ASP. NET MVC RedirectToAction метод. Чтобы предотвратить отображение формы в ответе в div, вы можете просто использовать фильтр ответов ajax для входящих ответов с $. ajaxSetup . Если ответ содержит перенаправление MVC, вы можете оценить это выражение на стороне JS. Пример кода для JS ниже:

    $.ajaxSetup({
        dataFilter: function (data, type) {
            if (data && typeof data == "string") {
                if (data.indexOf('window.location') > -1) {
                    eval(data);
                }
            }
            return data;
        }
    });
    

    Если данные: "окно. location = '/ Account / Login' ", указанный выше фильтр поймает это и оценит перенаправление вместо того, чтобы позволить отображению данных.

    ответ дан Przemek Marcinkiewicz, с репутацией 752, 27.10.2016
  • 16 рейтинг

    Собираем слова Владимира Прудникова и Томаса Хансена:

    • Измените код на стороне сервера, чтобы определить, является ли он XHR. Если это так, установите код ответа перенаправления на 278. В Джанго:
       if request.is_ajax():
          response.status_code = 278
    

    Это заставляет браузер воспринимать ответ как успешный и передает его в свой Javascript.

    • В вашем JS убедитесь, что отправка формы осуществляется через Ajax, проверьте код ответа и при необходимости перенаправьте:
    $('#my-form').submit(function(event){ 
    
      event.preventDefault();   
      var options = {
        url: $(this).attr('action'),
        type: 'POST',
        complete: function(response, textStatus) {    
          if (response.status == 278) { 
            window.location = response.getResponseHeader('Location')
          }
          else { ... your code here ... } 
        },
        data: $(this).serialize(),   
      };   
      $.ajax(options); 
    });
    
    ответ дан Graham King, с репутацией 2695, 6.08.2009
  • 16 рейтинг

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

    $(document).ready(function ()
    {
        $(document).ajaxSend(
        function(event,request,settings)
        {
            var intercepted_success = settings.success;
            settings.success = function( a, b, c ) 
            {  
                if( request.responseText.indexOf( "" ) > -1 )
                    window.location = window.location;
                else
                    intercepted_success( a, b, c );
            };
        });
    });
    

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

    ответ дан Timmerz, с репутацией 4567, 17.08.2010
  • 12 рейтинг

    Хотя ответы, кажется, работают для людей, если вы используете Spring Security, я обнаружил, что расширение LoginUrlAuthenticationEntryPoint и добавление специального кода для обработки AJAX более надежны. Большинство примеров перехватывают , все перенаправляют не только ошибки аутентификации. Это было нежелательно для проекта, над которым я работаю. Может также возникнуть необходимость расширить ExceptionTranslationFilter и переопределить метод «sendStartAuthentication», чтобы удалить шаг кэширования, если вы не хотите, чтобы невыполненный запрос AJAX кэшировался.

    Пример AjaxAwareAuthenticationEntryPoint:

    public class AjaxAwareAuthenticationEntryPoint extends
        LoginUrlAuthenticationEntryPoint {
    
        public AjaxAwareAuthenticationEntryPoint(String loginUrl) {
            super(loginUrl);
        }
    
        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
            if (isAjax(request)) {
                response.sendError(HttpStatus.UNAUTHORIZED.value(), "Please re-authenticate yourself");
            } else {
            super.commence(request, response, authException);
            }
        }
    
        public static boolean isAjax(HttpServletRequest request) {
            return request != null && "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
        }
    }
    

    Источники: 1 , 2

    ответ дан John, с репутацией 342, 17.09.2013
  • 12 рейтинг
        
    
    
    ответ дан Priyanka, с репутацией 147, 10.09.2011
  • 12 рейтинг

    Попробуйте

        $(document).ready(function () {
            if ($("#site").length > 0) {
                window.location = "<%= Url.Content("~") %>" + "Login/LogOn";
            }
        });
    

    Поместите его на страницу входа. Если он был загружен в div на главной странице, он будет перенаправлять на страницу входа. «#site» - это идентификатор div, который находится на всех страницах, кроме страницы входа.

    ответ дан podeig, с репутацией 1146, 5.10.2010
  • 11 рейтинг

    Я решил это, добавив следующее в мой логин. страница php.

    
    
    
    ответ дан Paul Richards, с репутацией 493, 5.12.2011
  • 7 рейтинг

    Некоторым может показаться полезным следующее:

    Я хотел, чтобы клиенты перенаправлялись на страницу входа для любого действия по отдыху, отправляемого без токена авторизации. Поскольку все мои остальные действия основаны на Ajax, мне понадобился хороший общий способ перенаправления на страницу входа вместо обработки функции успеха Ajax.

    Вот что я сделал:

    На любой запрос Ajax мой сервер будет возвращать ответ Json 200 «НЕОБХОДИМО АУТЕНТИФИЦИРОВАТЬ» (если клиенту требуется аутентификация).

    Простой пример на Java (на стороне сервера):

    @Secured
    @Provider
    @Priority(Priorities.AUTHENTICATION)
    public class AuthenticationFilter implements ContainerRequestFilter {
    
        private final Logger m_logger = LoggerFactory.getLogger(AuthenticationFilter.class);
    
        public static final String COOKIE_NAME = "token_cookie"; 
    
        @Override
        public void filter(ContainerRequestContext context) throws IOException {        
            // Check if it has a cookie.
            try {
                Map cookies = context.getCookies();
    
                if (!cookies.containsKey(COOKIE_NAME)) {
                    m_logger.debug("No cookie set - redirect to login page");
                    throw new AuthenticationException();
                }
            }
            catch (AuthenticationException e) {
                context.abortWith(Response.ok("\"NEED TO AUTHENTICATE\"").type("json/application").build());
            }
        }
    }
    

    В своем Javascript я добавил следующий код:

    $.ajaxPrefilter(function(options, originalOptions, jqXHR) {
        var originalSuccess = options.success;
    
        options.success = function(data) {
            if (data == "NEED TO AUTHENTICATE") {
                window.location.replace("/login.html");
            }
            else {
                originalSuccess(data);
            }
        };      
    });
    

    И это все.

    ответ дан Tomer, с репутацией 164, 8.04.2016
  • 6 рейтинг

    Позвольте мне еще раз процитировать проблему, как описано @Steg

    У меня была похожая проблема с твоей. Я выполняю запрос AJAX, который имеет 2 возможные ответы: тот, который перенаправляет браузер на новую страницу и тот, который заменяет существующую HTML-форму на текущей странице новой один.

    ИМХО, это реальная проблема, и ее придется официально распространить на текущие стандарты HTTP.

    Я считаю, что новый стандарт Http будет использовать новый код состояния. значение: в настоящее время 301/302 говорит браузеру пойти и извлечь содержимое этого запроса к новому location.

    В расширенном стандарте будет сказано, что если ответ status: 308 (просто пример), то браузер должен перенаправить главную страницу на предоставленный location.

    Это, как говорится; Я склонен уже подражать этому будущему поведению и, следовательно, когда документ. нужен редирект, у меня сервер отвечает как:

    status: 204 No Content
    x-status: 308 Document Redirect
    x-location: /login.html
    

    Когда JS получает «status: 204», он проверяет наличие заголовка x-status: 308 и создает документ. перенаправить на страницу, указанную в заголовке location.

    Имеет ли это какой-то смысл для вас?

    ответ дан Chaim Klar, с репутацией 81, 12.07.2018
  • 5 рейтинг

    в сервлете нужно поставить response.setStatus(response.SC_MOVED_PERMANENTLY); чтобы отправить «301» статус xmlHttp, необходимый для перенаправления. , ,

    и в $. Функция ajax Вы не должны использовать функцию .toString(). , , всего

    if (xmlHttp.status == 301) { top.location.href = 'xxxx.jsp'; }

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

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

    ответ дан Vladimir Prudnikov, с репутацией 3702, 14.11.2008
  • 5 рейтинг

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

    Мой тип приложения на сервере - Asp.Net MVC, и у него есть хорошее место для этого. в Global.asax я реализовал событие Application_EndRequest так:

        public class MvcApplication : System.Web.HttpApplication
        {
    
        //  ...
        //  ...
    
            protected void Application_EndRequest(object sender, EventArgs e)
            {
                var app = (HttpApplication)sender;
                app.Context.Response.Headers.Add("CurrentUrl",app.Context. Request.CurrentExecutionFilePath);
            }
    
        }
    

    Это прекрасно работает для меня! Теперь в каждом ответе JQuery $.post у меня есть запрошенный url, а также другие заголовки ответа, полученные в результате метода POST со статусом 302, 303,. , , ,

    и другая важная вещь: нет необходимости изменять код на стороне сервера или на стороне клиента.

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

    Я написал это, может быть, помочь кому-то :)

    ответ дан Ali Adlavaran, с репутацией 2553, 30.07.2015
  • 5 рейтинг

    У меня не было никакого успеха с решением заголовка - они никогда не были подобраны в моем методе ajaxSuccess / ajaxComplete. Я использовал ответ Steg с пользовательским ответом, но я изменил часть JS. Я настраиваю метод, который я вызываю в каждой функции, чтобы я мог использовать стандартные методы $.get и $.post.

    function handleAjaxResponse(data, callback) {
        //Try to convert and parse object
        try {
            if (jQuery.type(data) === "string") {
                data = jQuery.parseJSON(data);
            }
            if (data.error) {
                if (data.error == 'login') {
                    window.location.reload();
                    return;
                }
                else if (data.error.length > 0) {
                    alert(data.error);
                    return;
                }
            }
        }
        catch(ex) { }
    
        if (callback) {
            callback(data);
        }
    }
    

    Пример использования. , ,

    function submitAjaxForm(form, url, action) {
        //Lock form
        form.find('.ajax-submit').hide();
        form.find('.loader').show();
    
        $.post(url, form.serialize(), function (d) {
            //Unlock form
            form.find('.ajax-submit').show();
            form.find('.loader').hide();
    
            handleAjaxResponse(d, function (data) {
                // ... more code for if auth passes ...
            });
        });
        return false;
    }
    
    ответ дан jocull, с репутацией 9108, 6.02.2013
  • 5 рейтинг

    Я просто хотел фиксировать любые запросы AJAX для всей страницы. @SuperG заставил меня начать. Вот что я закончил:

    // redirect ajax requests that are redirected, not found (404), or forbidden (403.)
    $('body').bind('ajaxComplete', function(event,request,settings){
            switch(request.status) {
                case 301: case 404: case 403:                    
                    window.location.replace("http://mysite.tld/login");
                    break;
            }
    });
    

    Я хотел специально проверить определенные коды состояния http, чтобы основывать свое решение на. Тем не менее, вы можете просто связаться с ajaxError, чтобы получить что-то кроме успеха (возможно, только 200? ) Я мог бы просто написать:

    $('body').bind('ajaxError', function(event,request,settings){
        window.location.replace("http://mysite.tld/login");
    }
    
    ответ дан Bretticus, с репутацией 826, 4.08.2010
  • 5 рейтинг

    Если вы также хотите передать значения, вы также можете установить переменные сеанса и доступ Например: В вашем JSP вы можете написать

    <% HttpSession ses = request.getSession(true);
       String temp=request.getAttribute("what_you_defined"); %>
    

    И затем вы можете сохранить это временное значение в переменной javascript и поиграть в

    ответ дан karthik339, с репутацией 183, 7.01.2013
  • 4 рейтинг

    У меня возникла эта проблема в приложении django, с которым я работаю (отказ от ответственности: я стараюсь учиться и ни в коем случае не эксперт) Я хотел использовать jQuery ajax для отправки запроса DELETE на ресурс, удалить его на стороне сервера, а затем отправить перенаправление обратно (в основном) на домашнюю страницу. Когда я отправил HttpResponseRedirect('/the-redirect/') из скрипта Python, метод jQuery ajax получал 200 вместо 302. Итак, что я сделал, чтобы отправить ответ 300 с:

    response = HttpResponse(status='300')
    response['Location'] = '/the-redirect/' 
    return  response
    

    Затем я отправил / обработал запрос на клиенте с помощью jQuery. Аякс вроде так:

    
    
    where *the-jquery* =
    $.ajax({ 
      type: 'DELETE', 
      url: '/resource-url/', 
      complete: function(jqxhr){ 
        window.location = jqxhr.getResponseHeader('Location'); 
      } 
    });
    

    Возможно, использование 300 не «правильно», но по крайней мере это сработало так, как я хотел.

    PS: редактировать мобильную версию SO было огромной болью. Глупый интернет-провайдер выполнил мой запрос на отмену услуги, когда я закончил с моим ответом!

    ответ дан Benny Jobigan, с репутацией 3336, 28.08.2011
  • 4 рейтинг

    Вы также можете перехватить прототип отправки XMLHttpRequest. Это будет работать для всех посылок (jQuery / dojo / etc) с одним обработчиком.

    Я написал этот код для обработки ошибки 500 страниц с истекшим сроком действия, но он должен работать так же хорошо, чтобы перехватить перенаправление 200. Подготовьте запись в Википедии на XMLHttpRequest onreadystatechange о значении readyState.

    // Hook XMLHttpRequest
    var oldXMLHttpRequestSend = XMLHttpRequest.prototype.send;
    
    XMLHttpRequest.prototype.send = function() {
      //console.dir( this );
    
      this.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 500 && this.responseText.indexOf("Expired") != -1) {
          try {
            document.documentElement.innerHTML = this.responseText;
          } catch(error) {
            // IE makes document.documentElement read only
            document.body.innerHTML = this.responseText;
          }
        }
      };
    
      oldXMLHttpRequestSend.apply(this, arguments);
    }
    
    ответ дан Curtis Yallop, с репутацией 4014, 10.04.2012
  • 1 рейтинг

    Кроме того, вы, вероятно, захотите перенаправить пользователя на указанный в заголовках URL-адрес. Итак, наконец, это будет выглядеть так:

    $.ajax({
        //.... other definition
        complete:function(xmlHttp){
            if(xmlHttp.status.toString()[0]=='3'){
            top.location.href = xmlHttp.getResponseHeader('Location');
        }
    });
    

    UPD: Opps. Есть та же задача, но она не работает. Заниматься этим Я покажу вам решение, когда найду его.

    ответ дан Vladimir Prudnikov, с репутацией 3702, 19.10.2008
  • 0 рейтинг

    Я получил рабочее решение, используя ответы @John и @Arpad ссылка и @RobWinch ссылка

    Я использую Spring Security 3. 2. 9 и JQuery 1. 10. 2.

    Расширить класс Spring, чтобы вызвать ответ 4XX только на запросы AJAX:

    public class CustomLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
    
        public CustomLoginUrlAuthenticationEntryPoint(final String loginFormUrl) {
            super(loginFormUrl);
        }
    
        // For AJAX requests for user that isn't logged in, need to return 403 status.
        // For normal requests, Spring does a (302) redirect to login.jsp which the browser handles normally.
        @Override
        public void commence(final HttpServletRequest request,
                             final HttpServletResponse response,
                             final AuthenticationException authException)
                throws IOException, ServletException {
            if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
                response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
            } else {
                super.commence(request, response, authException);
            }
        }
    }
    

    applicationContext-security. xml

      
            
         
        
    ...
        
            
        
    ...
    
        
          
            
              
                
                  
                
                
                
              
            
          
        
    
    

    В моих JSP добавьте глобальный обработчик ошибок AJAX, как показано здесь

      $( document ).ajaxError(function( event, jqxhr, settings, thrownError ) {
          if ( jqxhr.status === 403 ) {
              window.location = "login.jsp";
          } else {
              if(thrownError != null) {
                  alert(thrownError);
              } else {
                  alert("error");
              }
          }
      });
    

    Также удалите существующие обработчики ошибок из вызовов AJAX на страницах JSP:

            var str = $("#viewForm").serialize();
            $.ajax({
                url: "get_mongoDB_doc_versions.do",
                type: "post",
                data: str,
                cache: false,
                async: false,
                dataType: "json",
                success: function(data) { ... },
    //            error: function (jqXHR, textStatus, errorStr) {
    //                 if(textStatus != null)
    //                     alert(textStatus);
    //                 else if(errorStr != null)
    //                     alert(errorStr);
    //                 else
    //                     alert("error");
    //            }
            });
    

    Я надеюсь, что это помогает другим.

    Обновление1 Я обнаружил, что мне нужно добавить параметр (always-use-default-target = "true") в конфигурацию form-login. Это было необходимо, поскольку после того, как запрос AJAX перенаправляется на страницу входа (из-за истекшего сеанса), Spring запоминает предыдущий запрос AJAX и автоматически перенаправляет его после входа в систему. Это заставляет возвращенный JSON отображаться на странице браузера. Конечно, не то, что я хочу.

    Обновление 2 Вместо always-use-default-target="true" используйте пример @RobWinch по блокировке AJAX-запросов от requstCache. Это позволяет обычным ссылкам перенаправляться на исходную цель после входа в систему, но AJAX переходят на домашнюю страницу после входа в систему.

    ответ дан Darren Parker, с репутацией 834, 21.03.2018
  • -2 рейтинг

    это сработало для меня:

    success: function(data, textStatus, xhr) {
    
            console.log(xhr.status);
    }
    

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

    ответ дан camara90100, с репутацией 351, 15.03.2014