javascript practices So verwalten Sie eine Weiterleitungsanforderung nach einem jQuery Ajax-Aufruf




jquery jsonpcallback (24)

Ich habe dieses Problem folgendermaßen gelöst:

Fügen Sie eine Middleware hinzu, um die Antwort zu verarbeiten. Wenn es sich um eine Weiterleitung für eine Ajax-Anfrage handelt, ändern Sie die Antwort auf eine normale Antwort mit der Weiterleitungs-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

Wenn dann in ajaxComplete die Antwort Umleitung enthält, muss es eine Weiterleitung sein, also ändern Sie den Standort des Browsers.

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

    }

Ich verwende $.post() , um ein Servlet unter Verwendung von Ajax aufzurufen und dann das resultierende HTML-Fragment zu verwenden, um ein div Element in der aktuellen Seite des Benutzers zu ersetzen. Wenn die Sitzung jedoch abläuft, sendet der Server eine Umleitungsdirektive, um den Benutzer zur Anmeldeseite zu senden. In diesem Fall ersetzt jQuery das Element div mit dem Inhalt der Anmeldeseite und zwingt die Augen des Benutzers, eine seltene Szene zu sehen.

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


I was having this problem on a django app I'm tinkering with (disclaimer: I'm tinkering to learn, and am in no way an expert). What I wanted to do was use jQuery ajax to send a DELETE request to a resource, delete it on the server side, then send a redirect back to (basically) the homepage. When I sent HttpResponseRedirect('/the-redirect/') from the python script, jQuery's ajax method was receiving 200 instead of 302. So, what I did was to send a response of 300 with:

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

Then I sent/handled the request on the client with jQuery.ajax like so:

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

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

Maybe using 300 isn't "right", but at least it worked just like I wanted it to.

PS :this was a huge pain to edit on the mobile version of SO. Stupid ISP put my service cancellation request through right when I was done with my answer!


Im Servlet sollten Sie response.setStatus(response.SC_MOVED_PERMANENTLY); um den Status '301' xmlHttp zu senden, den Sie für eine Weiterleitung benötigen ...

und in der $ .ajax-Funktion sollten Sie nicht nur die .toString() Funktion verwenden

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

Das Problem ist, dass es nicht sehr flexibel ist, man kann nicht entscheiden, wohin man umleiten möchte.

Das Umleiten durch die Servlets sollte der beste Weg sein. aber ich kann immer noch nicht den richtigen Weg finden, es zu tun.


Während die Antworten für Leute zu funktionieren scheinen, wenn Sie Spring Security verwenden, habe ich gefunden, LoginUrlAuthenticationEntryPoint zu erweitern und spezifischen Code hinzuzufügen, um AJAX robuster zu behandeln. Die meisten Beispiele fangen alle Weiterleitungen ab, nicht nur Authentifizierungsfehler. Dies war für das Projekt, an dem ich arbeite, nicht wünschenswert. Möglicherweise müssen Sie auch ExceptionTranslationFilter erweitern und die Methode "sendStartAuthentication" überschreiben, um den Zwischenspeicherungsschritt zu entfernen, wenn die fehlgeschlagene AJAX-Anforderung nicht zwischengespeichert werden soll.

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

}

Quellen: 1 , 2


Ich denke, ein besserer Weg, dies zu handhaben, besteht darin, die vorhandenen Antwortcodes des HTTP-Protokolls zu nutzen, insbesondere 401 Unauthorized .

Hier ist, wie ich es gelöst habe:

  1. Server-Seite: Wenn die Sitzung abläuft und die Anfrage Ajax ist. sende einen 401-Antwort-Code-Header
  2. Client-Seite: Bindet 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, das ist generischer und Sie schreiben keine neue benutzerdefinierte Spezifikation / Kopfzeile. Sie sollten auch keine Ihrer bestehenden Ajax-Anrufe ändern müssen.

Edit: Per @ Rob Kommentar unten, 401 (der HTTP-Status-Code für Authentifizierungsfehler) sollte der Indikator sein. Weitere Informationen finden Sie unter 403 Verbotene vs 401 nicht autorisierte HTTP-Antworten . Einige Web-Frameworks verwenden 403 sowohl für Authentifizierungs- als auch für Autorisierungsfehler - passen Sie sich entsprechend an. Danke, Rob.


Die meisten der angegebenen Lösungen verwenden eine Problemumgehung, indem sie einen zusätzlichen Header oder einen unangemessenen HTTP-Code verwenden. Diese Lösungen werden höchstwahrscheinlich funktionieren, fühlen sich aber ein wenig "hacky" an. Ich habe eine andere Lösung gefunden.

Wir verwenden WIF, das für eine Umleitung konfiguriert ist (passiveRedirectEnabled = "true") bei einer 401-Antwort. Die Umleitung ist nützlich, wenn normale Anfragen bearbeitet werden, funktioniert aber nicht für AJAX-Anfragen (da Browser die 302 / Umleitung nicht ausführen).

Mit dem folgenden Code in Ihrer global.asax können Sie die Weiterleitung für AJAX-Anfragen deaktivieren:

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

Dadurch können Sie 401 Antworten für AJAX-Anfragen zurückgeben, die Ihr JavaScript dann durch erneutes Laden der Seite verarbeiten kann. Beim Neuladen der Seite wird eine 401 ausgelöst, die von WIF verarbeitet wird (und WIF leitet den Benutzer zur Anmeldeseite um).

Ein Beispiel Javascript um 401 Fehler zu behandeln:

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

Eine andere Lösung, die ich gefunden habe (besonders nützlich, wenn Sie ein globales Verhalten festlegen wollen), ist die Verwendung der $.ajaxsetup() Methode zusammen mit der Eigenschaft statusCode . Wie bereits erwähnt, sollten Sie keinen Umleitungsstatuscode ( 3xx ) verwenden, stattdessen einen 4xx Statuscode verwenden und die Umleitung clientseitig handhaben.

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

Ersetzen Sie 400 durch den Statuscode, den Sie behandeln möchten. Wie bereits erwähnt, könnte 401 Unauthorized eine gute Idee sein. Ich benutze die 400 da es sehr unspezifisch ist und ich kann die 401 für spezifischere Fälle (wie falsche Login-Daten) verwenden. Anstatt also direkt umzuleiten, sollte Ihr Backend einen 4xx Fehlercode zurückgeben, wenn die Sitzung abgelaufen ist und Sie die Client-Seite umleiten. Funktioniert perfekt für mich auch mit Frameworks wie backbone.js


You can also hook XMLHttpRequest send prototype. This will work for all sends (jQuery/dojo/etc) with one handler.

I wrote this code to handle a 500 page expired error, but it should work just as well to trap a 200 redirect. Ready the wikipedia entry on XMLHttpRequest onreadystatechange about the meaning of 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);
}

Versuchen

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

Legen Sie es auf die Login-Seite. Wenn es in einem div auf der Hauptseite geladen wurde, wird es auf die Anmeldeseite umgeleitet. "#site" ist eine ID eines div, das sich auf allen Seiten außer der Login-Seite befindet.


Verwenden Sie den Low-Level-Aufruf von $.ajax() :

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

Wenn Sie die Werte auch übergeben möchten, können Sie auch die Sitzungsvariablen festlegen und auf Eg zugreifen: In Ihrem JSP können Sie schreiben

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

Und dann können Sie diesen temporären Wert in Ihrer Javascript-Variable speichern und herumspielen


Ich habe eine einfache Lösung, die für mich funktioniert, keine Änderung des Servercodes erforderlich ... füge einfach ein Teelöffel Muskat hinzu ...

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

Ich überprüfe das Vorhandensein von html-Tags, aber Sie können indexOf ändern, um nach dem einzigartigen String auf Ihrer Login-Seite zu suchen ...


Einige könnten das Folgende nützlich finden:

Ich wollte, dass Clients auf die Anmeldeseite für alle Ruheaktionen umgeleitet werden, die ohne Autorisierungstoken gesendet werden. Da alle meine Ruheaktionen auf Ajax basieren, brauchte ich eine gute allgemeine Möglichkeit, um auf die Anmeldeseite umzuleiten, anstatt die Ajax-Erfolgsfunktion zu bearbeiten.

Das habe ich getan:

Bei jeder Ajax-Anfrage gibt mein Server eine JSON-200-Antwort "BENÖTIGT ZU AUTHENTISIEREN" zurück (wenn der Client sich authentifizieren muss).

Einfaches Beispiel in Java (serverseitig):

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

In meinem Javascript habe ich den folgenden Code hinzugefügt:

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

Und das ist es auch schon.


I got a working solulion using the answers from @John and @Arpad .com/a/8426947/4505142 and @RobWinch link

I use Spring Security 3.2.9 and jQuery 1.10.2.

Extend Spring's class to cause 4XX response only from AJAX requests:

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>

In my JSPs, add a global AJAX error handler as shown here

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

Also, remove existing error handlers from AJAX calls in JSP pages:

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

I hope it helps others.

Update1 I found that I needed to add the option (always-use-default-target="true") to the form-login config. This was needed since after an AJAX request gets redirected to the login page (due to expired session), Spring remembers the previous AJAX request and auto redirects to it after login. This causes the returned JSON to be displayed on the browser page. Of course, not what I want.

Update2 Instead of using always-use-default-target="true" , use @RobWinch example of blocking AJAX requests from the requstCache. This allows normal links to be redirected to their original target after login, but AJAX go to the home page after login.


das hat bei mir funktioniert:

success: function(data, textStatus, xhr) {

        console.log(xhr.status);
}

Bei Erfolg erhält Ajax den gleichen Statuscode, den der Browser vom Server erhält, und führt ihn aus.


Ich wollte nur meinen Ansatz teilen, da dies vielleicht jemandem helfen könnte:

Ich habe im Grunde ein JavaScript-Modul, das die Authentifizierung Dinge wie die Anzeige des Benutzernamens und auch diesen Fall behandelt die Umleitung auf die Anmeldeseite behandelt .

Mein Szenario: Wir haben grundsätzlich einen ISA-Server dazwischen, der alle Anfragen abhört und mit einem 302 und einem Location-Header auf unserer Login-Seite antwortet .

In meinem JavaScript-Modul war mein erster Ansatz so etwas wie

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

Das Problem (so viele hier bereits erwähnt) ist, dass der Browser die Weiterleitung selbst übernimmt, weshalb mein ajaxComplete Callback nie aufgerufen wurde, sondern ich bekam die Antwort der bereits umgeleiteten Login Seite, die offensichtlich einen status 200 . Das Problem: Wie erkennen Sie, ob die erfolgreiche 200er-Antwort Ihre eigentliche Login-Seite oder nur eine beliebige andere Seite ist?

Die Lösung

Da ich 302 Weiterleitungsantworten nicht erfassen konnte, habe ich auf meiner Anmeldeseite einen LoginPage Header hinzugefügt, der die URL der Anmeldeseite selbst enthielt. Im Modul höre ich jetzt nach dem Header und mache eine Weiterleitung:

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

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


Schließlich löse ich das Problem, indem ich einen benutzerdefinierten HTTP Header hinzufüge. Just before response for every request in server side, i add the current requested url to response's header.

My application type on server is Asp.Net MVC , and it has a good place to do it. in Global.asax i implemented the Application_EndRequest event so:

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

    }

It works perfect for me! Now in every response of the JQuery $.post i have the requested url and also other response headers which comes as result of POST method by status 302 , 303 ,... .

and other important thing is that there is no need to modify code on server side nor client side.

and the next is the ability to get access to the other information of post action such errors, messages, and ..., In this way.

I posted this, maybe help someone :)


Ich hatte keinen Erfolg mit der Header-Lösung - sie wurden nie in meiner ajaxSuccess / ajaxComplete-Methode abgeholt. Ich habe Stegs Antwort mit der benutzerdefinierten Antwort verwendet, aber ich habe die JS-Seite etwas modifiziert. Ich richte eine Methode ein, die ich in jeder Funktion $.get damit ich die Standardmethoden $.get und $.post verwenden kann.

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

Beispiel dafür ...

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

Ich wollte mich nur an irgendwelche Ajax-Anfragen für die gesamte Seite halten. @SuperG hat mich angefangen. Hier ist, womit ich endete:

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

Ich wollte gezielt nach bestimmten http-Statuscodes suchen, um meine Entscheidung zu treffen. Du kannst aber nur an ajaxError binden, um etwas anderes als Erfolg zu bekommen (200 nur vielleicht?) Ich hätte einfach schreiben können:

$('body').bind('ajaxError', function(event,request,settings){
    window.location.replace("http://mysite.tld/login");
}

Ich mag Timmerz 'Methode mit einer leichten Zitronenverdrehung. Wenn Sie jemals contentType von text / html erhalten, wenn Sie JSON erwarten, werden Sie höchstwahrscheinlich umgeleitet. In meinem Fall lade ich einfach die Seite neu und es wird auf die Anmeldeseite umgeleitet. Oh, und überprüfen Sie, dass der jqXHR-Status 200 ist, was albern erscheint, weil Sie in der Fehlerfunktion sind, richtig? Andernfalls erzwingen legitime Fehlerfälle ein iteratives Neuladen (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();
    }

});

Keine Browser verarbeiten 301 und 302 Antworten korrekt. Und tatsächlich sagt der Standard sogar, dass sie "transparent" mit ihnen umgehen sollten, was für die Ajax-Bibliotheksverkäufer ein MASSIVER Kopfschmerz ist. In Ra-Ajax wir den HTTP-Response-Status-Code 278 (nur einen "unbenutzten" Erfolgscode) verwenden, um transparent vom Server weiterleiten zu können ...

Das ärgert mich wirklich, und wenn jemand hier im W3C etwas "ziehen" würde, würde ich es begrüßen, wenn Sie W3C mitteilen könnten , dass wir 301 und 302 Codes wirklich selbst behandeln müssen ...! ;)


Ich weiß, dass dieses Thema alt ist, aber ich gebe noch einen anderen Ansatz, den ich hier gefunden und beschrieben here . Grundsätzlich verwende ich ASP.MVC mit WIF (aber das ist nicht wirklich wichtig für den Kontext dieses Themas - Antwort ist angemessen, egal welche Frameworks verwendet werden. Der Hinweis bleibt unverändert - Umgang mit Problemen im Zusammenhang mit Authentifizierungsfehlern beim Ausführen von Ajax-Anfragen ) .

Der unten gezeigte Ansatz kann auf alle Ajax-Anfragen out-of-the-box angewendet werden (wenn sie nicht vor Ereignis senden offensichtlich 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, wird die CheckPulse Methode aufgerufen (die Controller-Methode, die am einfachsten sein kann):

[Authorize]
public virtual void CheckPulse() {}

Wenn der Benutzer nicht authentifiziert ist (Token ist abgelaufen), kann auf diese Methode nicht zugegriffen werden (geschützt durch Authorize Attribut). Da das Framework die Authentifizierung behandelt, während das Token abläuft, setzt es den HTTP-Status 302 auf die Antwort. Wenn Sie nicht möchten, dass Ihr Browser 302 response transparent behandelt, fangen Sie ihn in Global.asax ab und ändern Sie den Antwortstatus - zum Beispiel auf 200 OK. Außerdem fügen Sie Header hinzu, der Sie anweist, solche Antworten auf spezielle Weise (später auf der Client-Seite) zu verarbeiten:

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 auf der Client-Seite nach solchen benutzerdefinierten Header suchen. Falls vorhanden, sollte eine vollständige Umleitung zur Anmeldeseite erfolgen (in meinem Fall wird window.location durch die URL aus der Anfrage ersetzt, die automatisch von meinem Framework bearbeitet 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;
                }
            }
    });
}

    <script>
    function showValues() {
        var str = $("form").serialize();
        $.post('loginUser.html', 
        str,
        function(responseText, responseStatus, responseXML){
            if(responseStatus=="success"){
                window.location= "adminIndex.html";
            }
        });     
    }
</script>

Was Vladimir Prudnikov und Thomas Hansen gesagt haben:

  • Ändern Sie Ihren serverseitigen Code, um festzustellen, ob es sich um ein XHR handelt. Wenn dies der Fall ist, setzen Sie den Antwortcode der Weiterleitung auf 278. In django:
   if request.is_ajax():
      response.status_code = 278

Dadurch behandelt der Browser die Antwort als erfolgreich und gibt sie an Ihr Javascript weiter.

  • Stellen Sie in Ihrem JS sicher, dass die Übermittlung des Formulars über Ajax erfolgt, überprüfen Sie den Antwortcode und leiten Sie bei Bedarf um:
$('#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); 
});






redirect