So verhindern Sie, dass Ajax-Anforderungen mithilfe von jQuery Weiterleitungen folgen

102

Ich verwende die jQuery-Ajax-Funktionen, um auf einen Webdienst zuzugreifen, aber der Server wird, anstatt eine Antwort mit einem Statuscode zurückzugeben, der ein Problem beschreibt, auf eine Seite mit einem 200-Header umgeleitet, die das Problem beschreibt. Ich kann daran keine Änderungen vornehmen, daher muss ich es irgendwie auf dem Client lösen.

Beispiel: Eine Anfrage geht an eine URL, die nicht gefunden wurde, sodass ich eine 302-Weiterleitung an einen anderen Ort erhalte. Eine neue Anfrage wird gesendet, und ich erhalte ein 200 OK, wodurch verhindert wird, dass der Fehlerrückruf ausgelöst wird.

Gibt es eine Möglichkeit, die Ajax-Anforderung zu verhindern, Weiterleitungen zu folgen und stattdessen einen Rückruf aufzurufen, vorzugsweise die Fehlermethode? Ist es alternativ möglich zu erkennen, ob im Client eine Umleitung stattgefunden hat?

Jørgen
quelle
8
Es ist seltsam, dass Ihr Backend 302 für einen nicht gefundenen anstelle eines 404
meldet.
Mögliches Duplikat von Umleitung von Xmlhttprequest verhindern
Benutzer

Antworten:

96

Ich finde Ihre Frage interessant, aber das Problem insgesamt scheint mir eher ein Missverständnis zu sein. Zumindest werde ich versuchen, mein Verständnis des Problems zu erklären.

Die stille (transparente) Umleitung ist Teil der XMLHttpRequestSpezifikation (siehe hier insbesondere die Worte "... folgen Sie transparent der Umleitung ..."). Der Standard erwähnt nur, dass der Benutzeragent (der Webbrowser) bestimmte Arten von automatischen Umleitungen verhindern oder benachrichtigen kann, dies ist jedoch kein Teil von XMLHttpRequest. Dies ist Teil der HTTP-Client-Konfiguration (Betriebssystemkonfiguration) oder der Webbrowser-Konfiguration. Sie jQuery.ajaxkönnen also keine Option haben, mit der Sie die Umleitung verhindern können.

Sie können sehen, dass die HTTP-Umleitung Teil des HTTP-Protokolls und nicht Teil von ist XMLHttpRequest. Es befindet sich also auf einer anderen Abstraktionsebene oder dem Netzwerkstapel. Beispielsweise können die Daten von der XMLHttpRequestvom HTTP-Proxy oder vom lokalen Browser-Cache abgerufen werden und sind Teil des HTTP-Protokolls. Meistens der Server der die Daten bereitstellt, und nicht der Client das Caching beeinflussen.

Sie können die Anforderung aus Ihrer Frage mit der Anforderung vergleichen, um zu verhindern, dass sich die IP-Adresse des Webservers oder die IP-Route während der Kommunikation ändert. All die Dinge können in einigen Szenarien interessant sein, aber es gibt Teile einer anderen Ebene des Kommunikationsstapels und können nicht von jQuery.ajaxoder verwaltet werdenXMLHttpRequest .

Der XMLHttpRequestStandard besagt, dass die Client-Konfiguration Optionen enthalten kann, die eine Umleitung verhindern. Im Fall von "Microsoft World", die ich besser kenne, können Sie sich die WinHttpSetOption- Funktion ansehen, WINHTTP_OPTION_DISABLE_FEATUREmit der die Option mit dem WINHTTP_DISABLE_REDIRECTSWert festgelegt werden kann. Ein anderer Weg ist die Verwendung der WINHTTP_OPTION_REDIRECT_POLICYOption mit dem WINHTTP_OPTION_REDIRECT_POLICY_NEVERWert. Eine weitere Funktion, die man in Windows verwenden kann, ist die WinHttpSetStatusCallback- Funktion, mit der die Rückruffunktion eingestellt werden kann, die einige Benachrichtigungen wie erhalten hat WINHTTP_CALLBACK_FLAG_REDIRECT.

Es ist also möglich, Ihre Anforderungen im Allgemeinen zu implementieren, aber die Lösung ist wahrscheinlich nicht unabhängig vom Betriebssystem oder vom Webbrowser und befindet sich nicht auf der Ebene von jQuery.ajaxoder XMLHttpRequest.

Oleg
quelle
2
Hervorragende Antwort mit großartigem Einblick! Ich habe einige Erfahrungen mit Locken, für die Sie ähnliche Flaggen setzen können, wie Sie erwähnen. Ich hatte gehofft, dass solche Anweisungen an den Browser übergeben werden könnten, aber aus Ihrer Antwort geht hervor, dass das erwartete Verhalten darin besteht, den Weiterleitungen so zu folgen, als ob die ursprüngliche Anforderung an den vom Server zugewiesenen Speicherort gesendet würde.
Jørgen
@ Jørgen: Gern geschehen! In den meisten Szenarien ist die Umleitung überhaupt kein Problem. Sie beschreiben nicht den Kontext, in dem Sie jQuery.ajax verwenden, und ob Sie die volle Kontrolle über den Webserver haben, an den Sie die Anforderung senden. Daher ist es schwierig, Ihnen andere Ratschläge zu geben, die Ihr Problem wirklich lösen können.
Oleg
Ich fürchte, ich kontrolliere die Serverseite nicht. Ich denke, meine beste Option ist es, den Antwortinhalt zu analysieren oder zu validieren.
Jørgen
@ Jørgen: Warum ist die Umleitung in Ihrem Fall ein Problem? Wenn der Server eine Seite vorübergehend oder dauerhaft an einen anderen Speicherort verschoben hat, kann er Ihre ursprüngliche Anforderung an den neuen Speicherort umleiten. Es wird absolut in Ordnung sein. Ein Administrator kann den Webserver so konfigurieren, dass er eine Umleitung ausführt, z. B. während des Wiederherstellungsvorgangs auf dem Server oder bei anderen Supportarbeiten. Wenn Sie den Server nach einer URL mit DNS fragen, kann der Administrator die IP-Zuordnung zu einem anderen Server ändern. Er kann die HTTP-Umleitung auf dieselbe Weise wie die DNS-Neukonfiguration durchführen. Was ist dein Problem?
Oleg
Mein Problem ist, dass die Umleitung zu einer allgemeinen Fehlerseite führt. Ich weiß, dass der Server anders eingerichtet sein sollte, aber jetzt muss ich eine Lösung für diese Situation finden.
Jørgen
23

Ich glaube nicht, dass es möglich ist. Die zugrunde liegende Bibliothek (XHR) macht die neue Anforderung transparent. Abgesehen davon habe ich in diesen Situationen (normalerweise ein Deal mit Sitzungszeitlimit, der mich zu einer Anmeldeseite führt) einen benutzerdefinierten Antwortheader zurückgesendet. Ich habe auch einen globalen Ajax-Handler eingerichtet, der das Vorhandensein dieses Headers überprüft und bei Vorhandensein angemessen reagiert (z. B. Umleiten der gesamten Seite zum Anmeldebildschirm).

Falls Sie interessiert sind, ist hier der jQuery-Code, den ich für diesen benutzerdefinierten Header beachten muss:

/* redirects main window when AJAX request indicates that the session has expired on the backend. */
function checkSession(event, xhr, ajaxOptions)
{
    if (xhr.readyState == 4)
    {
        if(xhr.getResponseHeader("Login-Screen") != null && xhr.getResponseHeader("Login-Screen").length)
        {
            window.location.href='sessionExpired.html'; //whatever
        }
    }
}

$(document).ajaxComplete(checkSession)
Jake Feasel
quelle
1
Danke, ich denke, ich muss mich mit einem ähnlichen Ansatz zufrieden geben und die Antwort analysieren.
Jørgen
11

Ich habe eine Funktion gefunden, mit der überprüft werden kann, ob Ihr Anruf umgeleitet wurde. Es ist xhr.state (): Wenn es "abgelehnt" ist, ist eine Umleitung aufgetreten.

Beispiel mit erfolgreichem Rückruf:

request.success(function(data, textStatus, xhr)
{
    if(xhr.state() == "resolved")
    {
        //no redirection
    }
    if(xhr.state() == "rejected")
    {
        //redirection
    }
});

Beispiel mit Fehlerrückruf:

request.error(function(xhr, textStatus)
{
    if (xhr.state() == "rejected")
    {
        //redirection
        location.href = "loginpage";
    } else
    {
        //some other error happened
        alert("error");
    }
});
Takman
quelle
1
Der Tipp in Ihrer Antwort hat uns wirklich geholfen, die Dinge zum Laufen zu bringen. Für Notizen, die anderen helfen würden, haben wir WebSphere Portal, dessen Sicherheit in SiteMinder integriert ist. Wir haben ein Portlet, das Ajax-Aufrufe an eine Ressourcen-URL benötigt, und wenn das Zeitlimit überschritten wird, werden transparente Weiterleitungen ausgeführt, aber wir können nicht weiterleiten, wie auf die Anmeldeseite umgeleitet wird. Das Überprüfen, ob jqXHR.state () "abgelehnt" wurde, hat sicherlich geholfen. Vielen Dank nochmal.
Uresh Kuruhuri
Toller Fund, es kann jedoch zu Fehlalarmen kommen, da der Status "Abgelehnt" ausgelöst werden kann, selbst wenn ein Versprechen abgelehnt wird und nicht nur bei Weiterleitung. jQuery erklärt, wann der Status "abgelehnt" gesendet wird api.jquery.com/deferred.state
Nitin
1

Ich kann unmöglich die aufschlussreiche Weisheit der vorherigen Codierer ergänzen, die geantwortet haben, aber ich werde einen bestimmten Fall hinzufügen, den andere möglicherweise nützlich finden, um darüber Bescheid zu wissen.

Ich bin auf diese stille 302-Weiterleitung im Kontext von SharePoint gestoßen. Ich habe einen einfachen Javascript-Clientcode, der eine SharePoint-Unterwebsite anpingt. Wenn eine 200-HTTP-Antwort empfangen wird, wird diese über auf diese Website verschobenwindow.location . Wenn es etwas anderes erhält, gibt es dem Benutzer einen Hinweis, dass die Site nicht existiert.

Wenn die Site jedoch vorhanden ist, der Benutzer jedoch keine Berechtigung hat, leitet SharePoint stillschweigend zu einer AccessDenied.aspx-Seite weiter. SharePoint hat den HTTP 401-Authentifizierungshandshake bereits auf Server- / Farmebene durchgeführt. Der Benutzer hat Zugriff auf SharePoint. Aber der Zugriff auf die Unterwebsite wird vermutlich über Datenbankflags abgewickelt. Die stille Umleitung umgeht meine "else" -Klausel, sodass ich meinen eigenen Fehler nicht auslösen kann. In meinem Fall ist dies kein Show-Stopper - es ist ein konsistentes vorhersehbares Verhalten. Aber es war ein wenig überraschend und ich habe dabei etwas über HTTP-Anfragen gelernt!

Chris van Hasselt
quelle
1

Ich war an der gleichen Sache interessiert und konnte die von Takman erwähntestate() Methode nicht finden und grub ein wenig für mich. Für die Leute, die hier auf der Suche nach einer Antwort auftauchen, sind hier meine Ergebnisse:

Wie bereits mehrfach erwähnt, können Sie Weiterleitungen nicht verhindern, aber erkennen. Laut MDN können Sie nach allen Weiterleitungen die responseURLvon verwenden XMLHttpRequestObject, die die endgültige URL enthält, von der die Antwort stammt. Die einzige Einschränkung ist, dass es von Internet Explorer nicht unterstützt wird (Edge hat es). Da das xhr/ jqXHRin die success/ done-Funktion von jquery eine Erweiterung des Ist ist XMLHttpRequest, sollte es auch dort verfügbar sein.

Rialgar
quelle
0

Ich nehme an, Sie erhalten eine Antwort von 200, da beim zweiten Mal keine Umleitung erfolgt, da die 404-Seite nicht abläuft und im Cache gespeichert wird. Das heißt, dass der Browser Ihnen die Seite im Cache zum zweiten Mal zur Verfügung stellt. In der Ajax-Abfrage befindet sich eine Eigenschaft "Cache". http://api.jquery.com/jQuery.ajax/

Sie sollten es auf "false" schreiben

netadictos
quelle
0

Während es in XmlHttpRequests nicht möglich ist, die Standortumleitung zu deaktivieren , ist dies bei Verwendung von fetch () der Fall :

fetch('url', {redirect: manual});
cweiske
quelle
Fetch sagt Ihnen nicht, wie die umgeleitete URL lautete. Sie können das Verhalten deaktivieren, aber "redirect: manual" soll nicht zulassen, dass der Benutzer die Weiterleitung selbst durchführt, und hat die Namensabsichten.
lcjury
-2

Ich bin nicht sicher, ob dies in Ihrem Fall zutrifft, aber Sie können Code schreiben, um auf bestimmte Statuscodes in der AJAX-Funktion zu reagieren.

$.ajax({
    url: '/admin/secret/data',
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    statusCode: {
        200: function (data) {
            alert('302: Occurred');
            // Bind the JSON data to the UI
        },
        401: function (data) {
            alert('401: Occurred');
            // Handle the 401 error here.
        }
    }
});
ipr101
quelle
9
Ich glaube nicht, dass dies zutrifft, da OP sagte, dass er aufgrund der Umleitung im Hintergrund immer einen 200-Statuscode erhält.
Ja, Barry,
-4

In den Anforderungsheadern im Fall einer Ajax-Anforderung haben Sie Folgendes

X-Requested-With    XMLHttpRequest

Nach diesen Kriterien auf der Serverseite können Sie Anforderungen filtern.

Gfox
quelle
Er wollte die Antwort überprüfen, nicht die Anfrage (über die er bereits die Kontrolle hat)
Ja, Barry
Vielleicht hat Gfox vorgeschlagen, dass für Ajax-Anfragen, die 3xx zurückgeben, sinnlos sind. Sie könnten diese Art von Anfrage filtern und beispielsweise 403 zurückgeben. Wenn Sie eine Website haben, auf der Seiten bereitgestellt werden, für die eine Formularauthentifizierung erforderlich ist, und diese Seiten auch Ajax-Aufrufe ausführen und Sie die Autorisierungslogik an einem Ort platzieren möchten, ist dies für mich eine gültige Antwort.
MaciejW