1532 Stimmen

Wie man eine Umleitungsanfrage nach einem jQuery Ajax-Aufruf verwaltet

Ich benutze $.post() um ein Servlet mit Ajax aufzurufen und dann das resultierende HTML-Fragment zu verwenden, um eine div Element auf der aktuellen Seite des Benutzers. Wenn die Sitzung jedoch beendet wird, sendet der Server eine Umleitungsanweisung, um den Benutzer zur Anmeldeseite zu schicken. In diesem Fall ersetzt jQuery das div Element mit dem Inhalt der Anmeldeseite und zwingt die Augen des Benutzers zu einem seltenen Anblick.

Wie kann ich eine Redirect-Direktive aus einem Ajax-Aufruf mit jQuery 1.2.6 verwalten?

1 Stimmen

(nicht eine Antwort als solche) - Ich habe dies in der Vergangenheit durch Bearbeiten der Jquery-Bibliothek und Hinzufügen einer Prüfung für die Login-Seite auf jedem XHR abgeschlossen getan. Nicht die beste Lösung, weil es jedes Mal getan werden müsste, wenn Sie aktualisieren, aber es löst das Problem.

1 Stimmen

Siehe dazugehörige Frage: stackoverflow.com/questions/5941933/

0 Stimmen

El HttpContext.Response.AddHeader und prüfen Sie den Erfolg von ajaxsetup

59voto

Till Punkte 21912

Verwenden Sie die Low-Level $.ajax() anrufen:

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

Versuchen Sie dies für eine Weiterleitung:

if (xmlHttp.code != 200) {
  top.location.href = '/some/other/page';
}

0 Stimmen

Ich habe versucht, das Zeug auf niedriger Ebene zu vermeiden. Wie auch immer, angenommen, ich verwende so etwas wie das, was Sie beschreiben, wie erzwinge ich eine Browserumleitung, sobald ich feststelle, dass der HTTP-Code 3xx ist? Mein Ziel ist es, den Benutzer umzuleiten und nicht nur mitzuteilen, dass seine Sitzung abgelaufen ist.

4 Stimmen

Btw, $.ajax() ist nicht sehr, sehr Low-Level. Es ist nur Low-Level in Bezug auf jQuery, weil es $.get, $.post, etc. gibt, die viel einfacher als $.ajax und alle seine Optionen sind.

0 Stimmen

Ja, ich jetzt mit JQuery ist nicht wirklich Low-Level, ich war dramatisch! BTW, Ihre Antwort war wirklich hilfreich. Danke!

36voto

Juri Punkte 31316

Ich wollte nur meine Herangehensweise mitteilen, weil sie vielleicht jemandem helfen könnte:

Ich habe im Grunde ein JavaScript-Modul eingebunden, das die Authentifizierung wie die Anzeige des Benutzernamens und in diesem Fall auch die Handhabung der Weiterleitung zur Anmeldeseite .

Mein Szenario: Wir haben im Grunde einen ISA-Server dazwischengeschaltet, der auf alle Anfragen hört und antwortet mit einer 302 und einem Standort-Header zu unserer Login-Seite.

In meinem JavaScript-Modul ist mein erster Ansatz war etwa so

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

Das Problem (wie viele hier bereits erwähnt haben) ist, dass der Browser die Weiterleitung selbst vornimmt, weshalb meine ajaxComplete Callback wurde nie aufgerufen, aber stattdessen erhielt ich die Antwort der bereits umgeleiteten Login-Seite was offensichtlich ein status 200 . Das Problem: Wie erkennen Sie, ob es sich bei der erfolgreichen 200-Antwort um Ihre eigentliche Anmeldeseite oder um eine beliebige andere Seite handelt?

Die Lösung

Da ich nicht in der Lage war, 302-Umleitungsantworten zu erfassen, habe ich eine LoginPage Kopfzeile auf meiner Anmeldeseite, die die URL der Anmeldeseite selbst enthielt. Im Modul lausche ich nun auf den Header und leite eine Umleitung ein:

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

...und das funktioniert wie geschmiert :). Sie fragen sich vielleicht, warum ich die URL in die LoginPage Kopfzeile...also im Grunde genommen, weil ich keine Möglichkeit gefunden habe, die Url von GET die sich aus der automatischen Standortumleitung vom xhr Objekt...

0 Stimmen

+1 - aber benutzerdefinierte Kopfzeilen sollten mit X- Eine bessere Überschrift wäre also X-LoginPage: http://example.com/login .

6 Stimmen

@ShaquinTrifonoff Jetzt nicht mehr. Ich habe das X- Präfix nicht verwendet, weil in Juni 2011 ein ITEF-Dokument schlug ihre Abschaffung vor, und tatsächlich, mit Juni 2012 ist es nicht mehr offiziell, dass benutzerdefinierte Kopfzeilen nicht mehr mit dem Präfix X- .

0 Stimmen

Wir haben auch einen ISA-Server, und ich bin gerade auf das gleiche Problem gestoßen. Anstatt es im Code zu umgehen, haben wir die Anweisungen in kb2596444 um ISA so zu konfigurieren, dass die Umleitung beendet wird.

31voto

jwaliszko Punkte 16494

Ich weiß, dass dieses Thema alt ist, aber ich werde noch einen weiteren Ansatz nennen, den ich gefunden und zuvor beschrieben habe aquí . Im Grunde bin ich mit ASP.MVC mit WIF (aber das ist für den Kontext dieses Themas nicht wirklich wichtig - die Antwort ist angemessen, egal welcher Rahmen verwendet wird. Der Hinweis bleibt unverändert - Umgang mit Problemen im Zusammenhang mit Authentifizierungsfehlern bei der Durchführung von Ajax-Anfragen) .

Der unten gezeigte Ansatz kann auf alle Ajax-Anfragen angewendet werden (sofern sie das Ereignis beforeSend nicht neu definieren).

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

Bevor eine Ajax-Anfrage ausgeführt wird CheckPulse Methode aufgerufen wird (die Controller-Methode, bei der es sich um die einfachste Methode handeln kann):

[Authorize]
public virtual void CheckPulse() {}

Wenn der Benutzer nicht authentifiziert ist (das Token ist abgelaufen), kann auf diese Methode nicht zugegriffen werden (geschützt durch Authorize Attribut). Da das Framework die Authentifizierung handhabt, während das Token abläuft, wird der http-Status 302 in die Antwort eingefügt. Wenn Sie nicht wollen, dass Ihr Browser die 302-Antwort transparent verarbeitet, fangen Sie sie in Global.asax ab und ändern Sie den Antwortstatus - zum Beispiel in 200 OK. Fügen Sie außerdem einen Header hinzu, der Sie anweist, diese Antwort auf besondere Weise zu verarbeiten (später auf der Client-Seite):

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

Schließlich wird auf der Client-Seite geprüft, ob eine solche benutzerdefinierte Kopfzeile vorhanden ist. Falls vorhanden, sollte eine vollständige Umleitung zur Anmeldeseite erfolgen (in meinem Fall window.location wird durch die URL der Anfrage ersetzt, die von meinem Framework automatisch verarbeitet wird).

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;
                }
            }
    });
}

0 Stimmen

Ich habe das Problem behoben, indem ich das PostAuthenticateRequest-Ereignis anstelle des EndRequest-Ereignisses verwendet habe.

0 Stimmen

@JaroslawWaliszko Ich habe in meiner letzten Antwort das falsche Ereignis eingefügt! Ich meinte das Ereignis PreSendRequestHeaders.....nicht PostAuthenticateRequest! >>schäm<< Danke für den Hinweis auf meinen Fehler.

0 Stimmen

@JaroslawWaliszko bei der Verwendung von WIF können Sie auch 401 Antworten für AJAX-Anfragen zurückgeben und lassen Sie Ihre Javascript behandeln diese. Außerdem gehst du davon aus, dass alle 302 eine Authentifizierung erfordern, was nicht in allen Fällen der Fall ist. Ich habe eine Antwort hinzugefügt, falls jemand daran interessiert ist.

30voto

rynop Punkte 45118

Ich denke, ein besserer Weg, dies zu handhaben, ist die Nutzung der bestehenden Antwortcodes des HTTP-Protokolls, insbesondere 401 Unauthorized .

Ich habe das Problem folgendermaßen gelöst:

  1. Serverseite: Wenn die Sitzung abläuft und die Anfrage ein Ajax ist, senden Sie einen 401 Response Code Header.
  2. Client-Seite: Bindung an die Ajax-Ereignisse

    $('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 ist dies allgemeiner und Sie schreiben keine neuen benutzerdefinierten Spezifikationen/Kopfzeilen. Sie sollten auch keine Ihrer bestehenden Ajax-Aufrufe ändern müssen.

Bearbeiten: Gemäß dem Kommentar von @Rob unten sollte 401 (der HTTP-Statuscode für Authentifizierungsfehler) der Indikator sein. Siehe 403 Verbotene vs. 401 Unerlaubte HTTP-Antworten für weitere Einzelheiten. Einige Web-Frameworks verwenden 403 sowohl für Authentifizierungs- als auch für Autorisierungsfehler - passen Sie sich also entsprechend an. Danke Rob.

0 Stimmen

Ich verfolge den gleichen Ansatz. Ruft jQuery wirklich ajaxSuccess auf 403 Fehlercode? Ich denke, nur ajaxError Teil ist tatsächlich erforderlich

25voto

Tyr Punkte 1029

Ich habe dieses Problem folgendermaßen gelöst:

Fügen Sie eine Middleware hinzu, um die Antwort zu verarbeiten. Wenn es sich um eine Umleitung für eine Ajax-Anfrage handelt, ändern Sie die Antwort in eine normale Antwort mit der Umleitungsurl.

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

Dann in ajaxComplete, wenn die Antwort enthält redirect, muss es eine Umleitung sein, so ändern Sie den Browser den Standort.

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X