заголовок не делает ничего [дубликат]

Вы можете создать переменную уровня класса для получения возвращаемого значения.

class A {
    int k = 0;
    private void f(Button b, int a){
        b.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(ClickEvent event) {
            k = a * 5;
        }
    });
}

теперь вы можете получить значение K и использовать его там, где хотите. экземпляр привязан к основному классу и может получить доступ к конечным локальным переменным его содержащего метода. Когда экземпляр использует конечный локальный из его содержащего метода, переменная сохраняет значение, которое оно удерживало во время создания экземпляра, даже если переменная вышла за пределы области (это, по сути, грубая ограниченная версия закрытия Java).

Поскольку локальный внутренний класс не является членом класса или пакета, он не объявляется с уровнем доступа. (Однако ясно, что его собственные члены имеют уровни доступа, как в обычном классе.)

1186
задан John Slegers 22 January 2016 в 21:21
поделиться

30 ответов

Решение, которое в итоге было реализовано, состояло в том, чтобы использовать оболочку для функции обратного вызова вызова 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, который мы используем для замены части страницы. Кроме того, нам нужно было перенаправить на страницу входа.

85
ответ дан radbyx 22 August 2018 в 16:50
поделиться
  • 1
    Обратите внимание, что это может быть сокращено до функции cbWrapper (funct) {return function (data) {if ($ («# myForm», data) .size () & gt; 0) top.location.href = «login»; else funct (data); }}. Тогда вам нужно только cbWrapper (myActualCB) при вызове .post. Да, код в комментариях - беспорядок, но следует отметить :) – Simen Echholt 18 November 2010 в 04:02
  • 2
    размер обесценивается, поэтому вы можете использовать .length здесь вместо размера – sunil 20 July 2016 в 10:46
  • 3
    я стараюсь, чтобы это не работало для меня – Koi To Hoga 12 June 2018 в 14:18

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

  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 = '/';
        }
    });
    
214
ответ дан 5 revs, 4 users 77%SuperG 22 August 2018 в 16:50
поделиться
  • 1
    Какое удивительное решение. Мне нравится идея универсального решения. Мне нужно проверить статус 403, но я могу использовать привязку ajaxSuccess для тела (это то, что я действительно искал.) Спасибо. – Bretticus 4 August 2010 в 18:21
  • 2
    Я просто сделал это и обнаружил, что мне нужен ajaxComplete, где я использовал функцию $ .get (), и любой статус, отличный от 200, не срабатывал. На самом деле, я мог бы, вероятно, просто привязан к ajaxError. См. Мой ответ ниже для более подробной информации. – Bretticus 4 August 2010 в 19:42
  • 3
    Во многих случаях это нормально, но что делать, если ваша структура обрабатывает авторизацию? – jwaliszko 18 June 2012 в 08:11
  • 4
    Мне нравится подход заголовка, но также думаю - как @ mwoods79 - что знание о том, куда перенаправить, не должно дублироваться. Я решил, что добавив заголовок REDIRECT_LOCATION вместо логического. – rintcius 24 November 2012 в 18:40
  • 5
    Позаботьтесь о том, чтобы настроить заголовок на ответ ПОСЛЕ перенаправления. Как описано в других ответах на этой странице, перенаправление может быть прозрачным для обработчика ajaxSucces. Таким образом, я включил заголовок в ответ GET на странице входа (что в конечном итоге и вызвало только запуск ajaxSuccess в моем сценарии). – sieppl 18 February 2013 в 16:35

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

$.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();
    }

});
59
ответ дан BrianY 22 August 2018 в 16:50
поделиться
  • 1
    спасибо Брайану, ваш ответ был лучшим для моего сценария, хотя я бы хотел, чтобы была более безопасная проверка, например, сравнение того, какой URL-адрес перенаправляется на страницу вместо простого «контента-типа», проверить. Мне не удалось найти, на какую страницу перенаправляется объект jqXHR. – Johnny 20 April 2012 в 21:32
  • 2
    Я проверил статус 401, а затем перенаправил. Работает как чемпион. – Eric 23 July 2015 в 20:41

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

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

106
ответ дан Gone Coding 22 August 2018 в 16:50
поделиться
  • 1
    Я за один шаг, который должен был обойтись без официального HTTP Spec. – Chris Marisic 7 June 2012 в 22:51
  • 2
    Разве это уже не прозрачно? Если ресурс перемещен, прозрачность его обработки означает повторение запроса по предоставленному URL-адресу. Это то, что я ожидаю, используя API XMLHttpRequest. – Philippe Rathé 12 September 2013 в 22:27
  • 3
    @ PhilippeRathé Согласитесь. Прозрачное обращение - это то, что я хочу. И я не знаю, почему это считается плохим. – smwikipedia 6 January 2016 в 14:19
  • 4
    @smwikipedia Чтобы организовать перенаправление разметки в главном разделе без перенаправления страницы. – cmc 6 June 2017 в 12:39

Я прочитал этот вопрос и внедрил подход, который был сформулирован относительно установки кода статуса ответа на 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 члена: data.redirect и data.form. Я нашел этот подход намного лучше.

633
ответ дан Steg 22 August 2018 в 16:50
поделиться
  • 1
    Как указано в решении в stackoverflow.com/questions/503093/… , лучше использовать window.location.replace (data.redirect); чем window.location.href = data.redirect; – Carles Barrobés 17 December 2010 в 14:05
  • 2
    Любая причина, по которой было бы нецелесообразно использовать HTTP-коды для действия. Например, код 307, который является временным перенаправлением HTTP? – Sergei Golos 24 February 2011 в 20:06
  • 3
    @Sergei Golos, причина в том, что если вы выполняете перенаправление HTTP, перенаправление на самом деле никогда не приходит к обратному вызову ajax. Браузер обрабатывает перенаправление, передавая код 200 с содержимым адресата перенаправления. – Miguel Silva 3 May 2011 в 04:08
  • 4
    Это работает, только если у вас есть контроль над сервером – h--n 1 January 2012 в 22:24
  • 5
    Этот ответ был бы более полезным, если бы он показал, как это делается на сервере. – Pedro Hoehl Carvalho 22 October 2015 в 14:01

Используйте низкоуровневый вызов $.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';
}
45
ответ дан Till 22 August 2018 в 16:50
поделиться
  • 1
    Я пытался избежать низкого уровня. В любом случае, предположим, что я использую что-то вроде того, что вы описываете, как я могу принудительно перенаправить браузер, как только обнаружим, что HTTP-код равен 3xx? Моя цель - перенаправить пользователя, а не просто объявить, что его сеанс истек. – Elliot Vargas 14 October 2008 в 14:25
  • 2
    Btw, $ .ajax () не очень, очень низкоуровневый. Это просто низкий уровень с точки зрения jQuery, потому что есть $ .get, $ .post и т. Д., Которые намного проще, чем $ .ajax и все его варианты. – Till 14 October 2008 в 14:31
  • 3
    О, парень! Извините, мне пришлось «не принимать». ваш ответ, он по-прежнему очень полезен. Вещь, перенаправления автоматически управляются XMLHttpRequest, поэтому я ВСЕГДА получаю код статуса 200 после перенаправления (вздох!). Я думаю, что мне придется делать что-то неприятное, как разбор HTML и поиск маркера. – Elliot Vargas 14 October 2008 в 16:19
  • 4
    Любопытно, если сеанс заканчивается на сервере, разве это не означает, что сервер отправляет другой SESSIONID? разве мы не могли бы это обнаружить? – Salamander2007 16 December 2008 в 02:35
  • 5
    ПРИМЕЧАНИЕ. Это не работает для перенаправления. ajax перейдет на новую страницу и вернет код состояния. – user 14 March 2010 в 05:34

Наконец, я решу проблему, добавив пользовательский 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, ....

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

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

Я разместил это, возможно, помог кому-то:)

5
ответ дан Ali Adlavaran 22 August 2018 в 16:50
поделиться

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

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

Затем я отправил / обработал запрос на клиенте с jQuery.ajax, например:

<button onclick="*the-jquery*">Delete</button>

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

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

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

4
ответ дан Benny Jobigan 22 August 2018 в 16:50
поделиться

Я просто хотел защелкнуться на любые запросы 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");
}
5
ответ дан Bretticus 22 August 2018 в 16:50
поделиться
  • 1
    последний скроет любые другие ошибки, затрудняющие поиск и устранение неисправностей – Tim Abell 8 August 2011 в 11:41
  • 2
    A 403 не означает, что пользователь не аутентифицирован, это означает, что (возможно, аутентифицированный) пользователь не имеет разрешения на просмотр запрашиваемого ресурса. Поэтому он не должен перенаправляться на страницу входа в систему – Rob 14 February 2014 в 15:37

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

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

ИМХО это является реальной проблемой и должен быть официально распространен на существующие HTTP-стандарты.

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

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

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

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

Когда JS получает " status: 204 ", он проверяет существование заголовка x-status: 308 и делает document.redirect на странице, представленной в заголовке location.

Это имеет для вас какое-то значение?

4
ответ дан Chaim Klar 22 August 2018 в 16:50
поделиться

Я думаю, что лучший способ справиться с этим - использовать существующие коды ответа 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.

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

26
ответ дан Community 22 August 2018 в 16:50
поделиться
  • 1
    Я использую тот же подход. Действительно ли jQuery вызывает ajaxSuccess на 403 код ошибки? Я думаю, что на самом деле нужна только часть ajaxError – Marius Balčytis 14 July 2013 в 22:14
  • 2
    Я исправил проблему, используя событие PostAuthenticateRequest вместо события EndRequest. – Frinavale 28 October 2013 в 18:38
  • 3
    @JaroslawWaliszko Я вложил неправильное событие в свой последний ответ! Я имел в виду событие PreSendRequestHeaders ..... не PostAuthenticateRequest! & GT; & GT; румяна & л; & л; спасибо за указание на мою ошибку. – Frinavale 28 October 2013 в 23:15
  • 4
    @JaroslawWaliszko при использовании WIF вы также можете вернуть 401 ответ на запросы AJAX и позволить вашему JavaScript обрабатывать их. Также вы предполагаете, что все 302 требуют аутентификации, которые могут быть неверными во всех случаях. Я добавил ответ, если кто-то заинтересован. – Rob 14 February 2014 в 16:01

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

Я написал этот код для обработки ошибки на 500 страниц с истекшим сроком действия, но он должен работать так же, как и ловушку перенаправления 200. Готов к записи wikipedia в 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);
}
4
ответ дан Curtis Yallop 22 August 2018 в 16:50
поделиться

У меня есть рабочий solulion, используя ответы от @John и @Arpad link и @RobWinch link

Я использую 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

  <security:http auto-config="false" use-expressions="true" entry-point-ref="customAuthEntryPoint" >
    <security:form-login login-page='/login.jsp' default-target-url='/index.jsp'                             
                         authentication-failure-url="/login.jsp?error=true"
                         />    
    <security:access-denied-handler error-page="/errorPage.jsp"/> 
    <security:logout logout-success-url="/login.jsp?logout" />
...
    <bean id="customAuthEntryPoint" class="com.myapp.utils.CustomLoginUrlAuthenticationEntryPoint" scope="singleton">
        <constructor-arg value="/login.jsp" />
    </bean>
...
<bean id="requestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache">
    <property name="requestMatcher">
      <bean class="org.springframework.security.web.util.matcher.NegatedRequestMatcher">
        <constructor-arg>
          <bean class="org.springframework.security.web.util.matcher.MediaTypeRequestMatcher">
            <constructor-arg>
              <bean class="org.springframework.web.accept.HeaderContentNegotiationStrategy"/>
            </constructor-arg>
            <constructor-arg value="#{T(org.springframework.http.MediaType).APPLICATION_JSON}"/>
            <property name="useEquals" value="true"/>
          </bean>
        </constructor-arg>
      </bean>
    </property>
</bean>

В моих 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");
//            }
        });

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

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

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

0
ответ дан Darren Parker 22 August 2018 в 16:50
поделиться

Объединив то, что сказал Владимир Прудников и Томас Хансен:

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

Это делает браузер успешным ответом на ответ.

  • В своем 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); 
});
15
ответ дан Graham King 22 August 2018 в 16:50
поделиться

У меня не было никакого успеха в решении заголовка - они никогда не были получены в моем методе ajaxSuccess / ajaxComplete. Я использовал ответ Штега с пользовательским ответом, но я немного изменил сторону 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;
}
5
ответ дан jocull 22 August 2018 в 16:50
поделиться

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

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

Мой сценарий: у нас в основном есть 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 ...

31
ответ дан Juri 22 August 2018 в 16:50
поделиться
  • 1
    +1 - но пользовательские заголовки должны начинаться с X-, поэтому лучшим заголовком для использования будет X-LoginPage: http://example.com/login. – uınbɐɥs 14 October 2012 в 05:01
  • 2
    @ShaquinTrifonoff Не больше. Я не использовал префикс X, потому что в июне 2011 года документ ITEF предложил свое осуждение, и, действительно, с June 2012 не является официальным, что пользовательские заголовки больше не должны быть с префиксом X-. – Juri 14 October 2012 в 08:31
  • 3
    У нас также есть ISA-сервер, и я просто столкнулся с той же проблемой. Вместо того, чтобы обойти это в коде, мы использовали инструкции в kb2596444 , чтобы настроить ISA для прекращения перенаправления. – scott stone 1 August 2013 в 22:44

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

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

. Затем вы можете сохранить это значение темпа в своем javascript переменная и игра вокруг

5
ответ дан karthik339 22 August 2018 в 16:50
поделиться

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

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

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

17
ответ дан morten.c 22 August 2018 в 16:50
поделиться
  • 1
    Где упомянуть функцию на странице? – Vikrant 27 January 2017 в 08:43
  • 2
    @Vikrant. Если я правильно понял ваш вопрос, вы можете вызвать функцию сразу после загрузки jQuery и до того, как будете выполнять свои фактические запросы. – morten.c 27 January 2017 в 17:52

Хотя ответы, похоже, работают для людей, если вы используете 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

17
ответ дан MRFrhn 22 August 2018 в 16:50
поделиться
  • 1
    Было бы полезно (для меня), если бы избиратели не объяснили, почему они голосуют. Если с этим решением есть что-то плохое, я хотел бы узнать из своих ошибок. Благодарю. – John 12 December 2013 в 22:50
  • 2
    Если вы используете Spring и также используете JSF, проверьте также: («partial / ajax»). EqualsIgnoreCase (request.getHeader («faces-request»)); – J Slick 24 March 2014 в 23:01
  • 3
    Пользователи могли проголосовать, потому что вы не упомянули: (1) необходимые мотивы на стороне клиента, чтобы обнаружить ваш ответ об ошибке; (2) необходимые моды к конфигурации Spring, чтобы добавить ваш настраиваемый LoginUrlAuthenticationEntryPoint в цепочку фильтров. – J Slick 24 March 2014 в 23:08
  • 4
    Ваш ответ подобен этому из @Arpad. Это сработало для меня; используя Spring Security 3.2.9. stackoverflow.com/a/8426947/4505142 – Darren Parker 21 March 2018 в 21:47

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

<script type="text/javascript">
    if (top.location.href.indexOf('login.php') == -1) {
        top.location.href = '/login.php';
    }
</script>
10
ответ дан Paul Richards 22 August 2018 в 16:50
поделиться

Попробуйте

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

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

11
ответ дан podeig 22 August 2018 в 16:50
поделиться
    <script>
    function showValues() {
        var str = $("form").serialize();
        $.post('loginUser.html', 
        str,
        function(responseText, responseStatus, responseXML){
            if(responseStatus=="success"){
                window.location= "adminIndex.html";
            }
        });     
    }
</script>
11
ответ дан Priyanka 22 August 2018 в 16:50
поделиться

Эта проблема может возникнуть при использовании метода 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;
    }
});

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

17
ответ дан Przemek Marcinkiewicz 22 August 2018 в 16:50
поделиться
  • 1
    data находится в теле ответа или заголовке? – GMsoF 12 May 2017 в 02:10

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

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

Используя следующий код в вашем global.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, которые будут обрабатываться WIF (и WIF перенаправит пользователя на страницу входа в систему).

Пример 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);
    }
});
16
ответ дан Rob 22 August 2018 в 16:50
поделиться

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

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

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

14
ответ дан Timmerz 22 August 2018 в 16:50
поделиться
  • 1
    Это, похоже, не работает для меня, он продолжает называть функцию, определенную с помощью вызова ajax, это похоже на то, что она не отменяет метод успеха. – adriaanp 24 August 2011 в 07:49

Некоторые могут найти ниже полезное:

Я хотел, чтобы клиенты были перенаправлены на страницу входа в систему для любого действия rest, которое отправляется без токена авторизации. Поскольку все мои действия по отдыху основаны на 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<String, Cookie> 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);
        }
    };      
});

И это все.

7
ответ дан Tomer 22 August 2018 в 16:50
поделиться

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

, а в функции $ .ajax вы не должны использовать .toString() function ..., just

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

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

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

5
ответ дан user 22 August 2018 в 16:50
поделиться

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

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

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

1
ответ дан Vladimir Prudnikov 22 August 2018 в 16:50
поделиться
  • 1
    Этот ответ должен быть удален автором, поскольку он сам говорит, что это не работает. Он может опубликовать рабочее решение позже. -1 – TheCrazyProgrammer 24 February 2017 в 02:14

Я знаю, что эта тема старая, но я дам еще один подход, который я нашел и ранее описал здесь здесь . В основном я использую 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;
                }
            }
    });
}
26
ответ дан Community 22 August 2018 в 16:50
поделиться
  • 1
    Я исправил проблему, используя событие PostAuthenticateRequest вместо события EndRequest. – Frinavale 28 October 2013 в 18:38
  • 2
    @JaroslawWaliszko Я вложил неправильное событие в свой последний ответ! Я имел в виду событие PreSendRequestHeaders ..... не PostAuthenticateRequest! & GT; & GT; румяна & л; & л; спасибо за указание на мою ошибку. – Frinavale 28 October 2013 в 23:15
  • 3
    @JaroslawWaliszko при использовании WIF вы также можете вернуть 401 ответ на запросы AJAX и позволить вашему JavaScript обрабатывать их. Также вы предполагаете, что все 302 требуют аутентификации, которые могут быть неверными во всех случаях. Я добавил ответ, если кто-то заинтересован. – Rob 14 February 2014 в 16:01

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

Добавить промежуточное программное обеспечение для обработки ответа, если оно является перенаправлением для запроса 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;
       }
   }
}
17
ответ дан MRFrhn 22 August 2018 в 16:50
поделиться
Другие вопросы по тегам:

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