Jak zarządzać żądaniem przekierowania po wywołaniu Jquery Ajax

Używam $.post() aby wywołać servlet za pomocą Ajax, a następnie używając wynikowego fragmentu HTML, aby zastąpić element div na bieżącej stronie użytkownika. Jeśli jednak sesja się skończy, serwer wysyła dyrektywę przekierowania, aby wysłać użytkownika na stronę logowania. W tym przypadku jQuery zastępuje element div zawartością strony logowania, zmuszając oczy użytkownika do bycia świadkiem rzadkiej sceny.

Jak zarządzać dyrektywą przekierowania z połączenia Ajax z jQuery 1.2.6?

Author: John Slegers, 2008-10-14

30 answers

Przeczytałem to pytanie i zaimplementowałem podejście, które zostało podane w odniesieniu do ustawiania kodu statusu odpowiedzi na 278, aby uniknąć przejrzyście obsługiwania przekierowań przez przeglądarkę. Mimo, że to działało, byłem trochę niezadowolony, ponieważ jest to trochę hack.

Po kolejnych Kopaniach porzuciłem to podejście i użyłem JSON . W tym przypadku wszystkie odpowiedzi na żądania ajax mają kod statusu 200, a treść odpowiedzi zawiera obiekt JSON, który jest zbudowany na serwerze. Javascript na kliencie może następnie użyć obiektu JSON, aby zdecydować, co ma zrobić.

Miałem podobny problem do twojego. Wykonuję żądanie ajax, który ma 2 możliwe odpowiedzi: jeden, który przekierowuje przeglądarkę do nowej strony i jeden, który zastępuje istniejący formularz HTML na bieżącej stronie z nową. Kod jquery do zrobienia tego wygląda mniej więcej tak:
$.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);
        }
    }
});

Obiekt JSON "data" jest zbudowany na serwerze tak, aby miał 2 członków: data.przekierowanie i data.forma. Uznałem to podejście za znacznie lepsze.

 638
Author: Steg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-07 22:54:26

Rozwiązałem ten problem przez:

  1. Dodanie niestandardowego nagłówka do odpowiedzi:

    public ActionResult Index(){
        if (!HttpContext.User.Identity.IsAuthenticated)
        {
            HttpContext.Response.AddHeader("REQUIRES_AUTH","1");
        }
        return View();
    }
    
  2. Powiązanie funkcji JavaScript z ajaxSuccess Zdarzenie i sprawdzenie, czy nagłówek istnieje:

    $(document).ajaxSuccess(function(event, request, settings) {
        if (request.getResponseHeader('REQUIRES_AUTH') === '1') {
           window.location = '/';
        }
    });
    
 216
Author: 5 revs, 4 users 77%SuperG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-08 08:15:21

Żadna przeglądarka nie obsługuje poprawnie odpowiedzi 301 i 302. W rzeczywistości standard mówi nawet, że powinni obsługiwać je "przejrzyście", co jest ogromnym bólem głowy dla dostawców bibliotek Ajax. W Ra-Ajax zostaliśmy zmuszeni do użycia kodu statusu odpowiedzi HTTP 278 (tylko jakiś" nieużywany " kod sukcesu) do obsługi przezroczystych przekierowań z serwera...

To mnie naprawdę irytuje, a jeśli ktoś tutaj ma jakieś "ciągnięcie" w W3C byłbym wdzięczny, gdybyś dał znać W3C , że naprawdę musimy sami obsługiwać kody 301 i 302...! ;)

 108
Author: Thomas Hansen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-19 08:03:56

Rozwiązaniem, które zostało ostatecznie zaimplementowane, było użycie wrappera do funkcji wywołania zwrotnego wywołania Ajax i w tym wrapperze sprawdzenie istnienia określonego elementu na zwracanym fragmencie HTML. Jeśli element został znaleziony, to wrapper wykonał przekierowanie. Jeśli nie, owijarka przekierowała połączenie do rzeczywistej funkcji zwrotnej.

Na przykład nasza funkcja wrappera była podobna do:

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

Następnie, wykonując wywołanie Ajax użyliśmy czegoś like:

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

Zadziałało to dla nas, ponieważ wszystkie wywołania Ajax zawsze zwracały HTML wewnątrz elementu DIV, którego używamy do zastąpienia fragmentu strony. Ponadto musieliśmy tylko przekierować na stronę logowania.

 87
Author: Elliot Vargas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-31 06:15:36

Podoba mi się metoda Timmerza z lekkim akcentem cytryny. Jeśli kiedykolwiek zwrócisz contentType z text/html Kiedy oczekujesz JSON, najprawdopodobniej zostaniesz przekierowany. W moim przypadku po prostu przeładowuję stronę i zostaje przekierowana na stronę logowania. I sprawdź, czy jqxhr ma status 200, co wydaje się głupie, ponieważ jesteś w funkcji błędu, prawda? W przeciwnym razie uzasadnione przypadki błędów wymuszą iteracyjne przeładowanie (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();
    }

});
 60
Author: BrianY,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-14 17:44:03

Użyj niskiego poziomu $.ajax() wywołanie:

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

Spróbuj przekierować:

if (xmlHttp.code != 200) {
  top.location.href = '/some/other/page';
}
 46
Author: Till,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-17 00:50:25

Chciałem się podzielić moim podejściem, ponieważ może to komuś pomóc:

W zasadzie włączyłem moduł JavaScript, który obsługuje uwierzytelnianie, takie jak wyświetlanie nazwy użytkownika, a także ten przypadek obsługi przekierowania na stronę logowania .

Mój scenariusz: w zasadzie mamy serwer ISA, pomiędzy którym nasłuchujemy wszystkich żądań i odpowiadamy 302 i nagłówkiem lokalizacji na naszą stronę logowania.

In my JavaScript module my initial podejście było czymś w rodzaju

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

Problem (jak wiele tutaj już wspomniano) jest to, że przeglądarka obsługuje przekierowanie przez siebie, dlatego mój ajaxComplete callback nigdy nie został wywołany, ale zamiast tego dostałem odpowiedź już przekierowanej strony logowania , która oczywiście była status 200. Problem: jak wykryć, czy udana odpowiedź 200 jest twoją rzeczywistą stroną logowania, czy tylko jakąś inną arbitralną stroną??

RozwiÄ…zanie

Ponieważ nie byłem w stanie przechwytywanie odpowiedzi przekierowujących 302, dodałem nagłówek LoginPage na mojej stronie logowania, który zawierał adres URL samej strony logowania. W module teraz słucham nagłówka i robię przekierowanie:

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

...i to działa jak urok:). Możesz się zastanawiać, dlaczego dodaję adres url w nagłówku LoginPage...w zasadzie dlatego, że nie znalazłem sposobu na określenie adresu url GET wynikającego z automatycznego przekierowania lokalizacji z obiektu xhr...

 32
Author: Juri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-23 10:02:27

Wiem, że ten temat jest stary, ale podam jeszcze jedno podejście, które znalazłem i wcześniej opisałem tutaj . Zasadniczo używam ASP.MVC z WIF (ale to nie jest tak naprawdę ważne dla kontekstu tego tematu-odpowiedź jest odpowiednia bez względu na to, które frameworki są używane. Wskazówka pozostaje bez zmian-rozwiązywanie problemów związanych z błędami uwierzytelniania podczas wykonywania żądań ajax) .

Podejście przedstawione poniżej może być zastosowane do wszystkich żądań ajax po wyjęciu z pudełka (jeśli nie redefiniują przed wydarzeniem oczywiście).

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

Przed wykonaniem dowolnego żądania ajax wywołana jest metoda CheckPulse (metoda kontrolera, która może być najprostsza):

[Authorize]
public virtual void CheckPulse() {}

Jeśli Użytkownik nie jest uwierzytelniony (token wygasł), nie można uzyskać dostępu do takiej metody (chronionej atrybutem Authorize). Ponieważ framework obsługuje uwierzytelnianie, podczas gdy token wygasa, nadaje odpowiedzi status http 302. Jeśli nie chcesz, aby twoja przeglądarka obsługiwała odpowiedź 302 w sposób przejrzysty, / align = "left" / asax i zmień status odpowiedzi - na przykład na 200 OK. Dodatkowo, dodaj nagłówek, który nakazuje Ci przetworzyć taką odpowiedź w specjalny sposób (później po stronie klienta):

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

Na koniec po stronie klienta sprawdź, czy nie ma takiego niestandardowego nagłówka. If present-pełne przekierowanie na stronę logowania (w moim przypadku {[6] } jest zastępowane przez url z żądania, który jest obsługiwany automatycznie przez mój framework).

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;
                }
            }
    });
}
 28
Author: jwaliszko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:26

Myślę, że lepszym sposobem radzenia sobie z tym jest wykorzystanie istniejących kodów odpowiedzi protokołu HTTP, w szczególności 401 Unauthorized.

Oto Jak to rozwiązałem:

  1. Po stronie serwera: jeśli sesja wygaśnie, a żądanie to ajax. wyślij nagłówek kodu odpowiedzi 401
  2. Client side: Bind do zdarzeń 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 jest to bardziej ogólne i nie piszesz nowego niestandardowego spec / nagłówka. Nie należy również modyfikować żadnego z istniejących ajax telefony.

Edit: za komentarz @Roba poniżej, 401 (kod statusu HTTP dla błędów uwierzytelniania) powinien być wskaźnikiem. Zobacz 403 Forbidden vs 401 Unauthorized HTTP responses aby uzyskać więcej szczegółów. W związku z tym niektóre frameworki internetowe używają 403 zarówno do błędów uwierzytelniania, jak i autoryzacji - dlatego odpowiednio się dostosowują. Dzięki Rob.

 22
Author: rynop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:26

Rozwiązałem ten problem tak:

Jeśli jest to przekierowanie dla żądania ajax, Zmień odpowiedź na normalną odpowiedź za pomocą adresu URL przekierowania.
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

Następnie w ajaxComplete, jeśli odpowiedź zawiera przekierowanie, musi to być przekierowanie, więc zmień lokalizację przeglądarki.

$('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;
       }
   }
}
 20
Author: Tyr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-13 12:54:03

Większość z podanych rozwiązań używa obejścia, używając dodatkowego nagłówka lub niepoprawnego kodu HTTP. Te rozwiązania prawdopodobnie zadziałają, ale czują się trochę "chwiejne". Wymyśliłem inne rozwiązanie.

Używamy WIF, który jest skonfigurowany do przekierowania (passiveRedirectEnabled= "true") na odpowiedź 401. Przekierowanie jest przydatne podczas obsługi zwykłych żądań, ale nie będzie działać dla żądań AJAX (ponieważ przeglądarki nie wykonają 302 / redirect).

Używając poniższego kodu w Twoim global.asax możesz wyłączyć przekierowanie dla żądań 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;
        }
    }

Pozwala to na zwrócenie 401 odpowiedzi dla żądań AJAX, które twój javascript może obsłużyć, przeładowując stronę. Przeładowanie strony spowoduje wyświetlenie 401, które będzie obsługiwane przez WIF (a WIF przekieruje użytkownika na stronę logowania).

Przykład javascript do obsługi błędów 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);
    }
});
 17
Author: Rob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-01 12:30:21

Innym rozwiązaniem, które znalazłem (szczególnie przydatne, jeśli chcesz ustawić globalne zachowanie) jest użycie $.ajaxsetup() Metoda wraz z statusCode własność . Jak zauważyli inni, nie używaj przekierowania statuscode (3xx), zamiast tego użyj 4xx statuscode i obsłuż przekierowanie po stronie klienta.

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

Zastąp 400 kodem stanu, który chcesz obsłużyć. Jak już wspomniano 401 Unauthorized może być dobrym pomysłem. Używam 400, ponieważ jest bardzo niespecyficzny i mogę użyć 401 w bardziej konkretnych przypadkach (np. błędne dane logowania). Więc zamiast przekierowywania bezpośrednio Twój backend powinien zwrócić kod błędu 4xx, gdy sesja się skończyła, a Ty zajmujesz się przekierowaniem po stronie klienta. Działa idealnie dla mnie nawet z frameworkami takimi jak backbone.js

 17
Author: morten.c,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-31 12:38:27

Ten problem może pojawić się wtedy za pomocą ASP.NET metoda przekierowywania MVC. Aby zapobiec wyświetlaniu odpowiedzi przez formularz w div, możesz po prostu zrobić jakiś filtr odpowiedzi ajax dla przypisania odpowiedzi za pomocą $.ajaxSetup . Jeśli odpowiedź zawiera przekierowanie MVC, możesz ocenić to wyrażenie po stronie JS. Przykładowy kod dla JS poniżej:

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

If data is: "window.location = '/Acount/Login'" powyższy filtr wyłapie to i oceni, aby przekierować zamiast umożliwienie wyświetlania danych.

 17
Author: Przemek Marcinkiewicz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-27 13:31:05

Zestawiając to, co Vladimir Prudnikov i Thomas Hansen powiedział:

  • ZmieÅ„ kod po stronie serwera, aby wykryć, czy jest to XHR. JeÅ›li tak, Ustaw kod odpowiedzi przekierowania na 278. W django:
   if request.is_ajax():
      response.status_code = 278

To sprawia, że przeglądarka traktuje odpowiedź jako sukces i przekazuje ją Twojemu Javascript.

  • w js upewnij siÄ™, że przesyÅ‚anie formularza odbywa siÄ™ za poÅ›rednictwem Ajax, sprawdź kod odpowiedzi i przekieruj w razie potrzeby:
$('#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); 
});
 16
Author: Graham King,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-06 20:17:07

Mam proste rozwiązanie, które działa dla mnie, nie trzeba zmieniać kodu serwera...wystarczy dodać łyżeczkę gałki muszkatołowej...

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

Sprawdzam obecność znacznika html, ale możesz zmienić indexOf, aby wyszukać dowolny unikalny ciąg znaków na stronie logowania...

 16
Author: Timmerz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-17 18:07:11

Try

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

Umieść go na stronie logowania. Jeśli został załadowany w div na stronie głównej, przekieruje do strony logowania. "#site " to identyfikator div, który znajduje się na wszystkich stronach z wyjątkiem strony logowania.

 12
Author: podeig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-29 08:31:30
    <script>
    function showValues() {
        var str = $("form").serialize();
        $.post('loginUser.html', 
        str,
        function(responseText, responseStatus, responseXML){
            if(responseStatus=="success"){
                window.location= "adminIndex.html";
            }
        });     
    }
</script>
 12
Author: Priyanka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-10 16:44:42

Podczas gdy odpowiedzi wydają się działać dla ludzi, jeśli używasz Spring Security znalazłem rozszerzenie LoginUrlAuthenticationEntryPoint i dodanie konkretnego kodu do obsługi AJAX bardziej solidne. Większość przykładów przechwytuje wszystkie przekierowania , a nie tylko błędy uwierzytelniania. Było to niepożądane dla projektu, nad którym pracuję. Możesz również znaleźć potrzebę rozszerzenia ExceptionTranslationFilter i nadpisać metodę "sendStartAuthentication", aby usunąć Krok buforowania, jeśli nie chcesz nieudane żądanie AJAX buforowane.

Przykład 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"));
    }
}

Źródła: 1, 2

 12
Author: John,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-13 13:08:09

Rozwiązałem to, umieszczając następujące elementy w moim loginie.strona php.

<script type="text/javascript">
    if (top.location.href.indexOf('login.php') == -1) {
        top.location.href = '/login.php';
    }
</script>
 11
Author: Paul Richards,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-05 19:59:00

Niektórzy mogą znaleźć poniżej przydatne:

Chciałem, aby klienci zostali przekierowani na stronę logowania dla każdej akcji rest, która jest wysyłana bez tokenu autoryzacji. Ponieważ wszystkie moje działania rest-są oparte na Ajax, potrzebowałem dobrego ogólnego sposobu przekierowania do strony logowania zamiast obsługi funkcji sukcesu Ajax.

Oto co zrobiłem:

Przy każdym żądaniu Ajax mój serwer zwróci odpowiedź Json 200 "NEED to AUTHENTICATE" (jeśli klient musi authenticate).

Prosty przykład w Javie (po stronie serwera):

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

W moim Javascript dodałem następujący kod:

$.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);
        }
    };      
});
I tyle.
 7
Author: Tomer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-08 23:26:17

Pozwolę sobie jeszcze raz zacytować problem opisany przez @Steg

Miałem podobny problem do twojego. Wykonuję żądanie ajax, które ma 2 możliwe odpowiedzi: takie, które przekierowują przeglądarkę na nową stronę i taki, który zastępuje istniejący formularz HTML na bieżącej stronie nowym jeden.

IMHO jest to prawdziwe wyzwanie i będzie musiało zostać oficjalnie rozszerzone do obecnych standardów HTTP.

Wierzę, że nowym standardem Http będzie użycie nowego status-kod. znaczenie: obecnie 301/302 mówi przeglądarce, aby poszła i pobrała zawartość tego żądania do nowego location.

W standardzie rozszerzonym będzie napisane, że jeśli odpowiedź status: 308 (tylko przykład), to przeglądarka powinna przekierować stronę główną do location podanego.

To powiedziawszy; jestem skłonny już naśladować to przyszłe zachowanie, a zatem, gdy dokument.przekierowanie jest potrzebne, mam odpowiedź serwera jako:

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

Kiedy js dostaje "status: 204", sprawdza istnienie nagłówka x-status: 308 i wykonuje dokument.przekierowanie do strony podanej w nagłówku location.

Czy to ma dla ciebie jakiÅ› sens?
 6
Author: Chaim Klar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-12 21:45:43

W servletie powinieneś umieścić response.setStatus(response.SC_MOVED_PERMANENTLY); aby wysłać status '301' XMLHTTP musisz przekierować...

I w $.funkcja ajax nie należy używać funkcji .toString()..., just

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

Problem w tym, że nie jest zbyt elastyczny, nie możesz zdecydować, gdzie chcesz przekierować..

Przekierowanie przez serwlety powinno być najlepszym sposobem. ale nadal nie mogę znaleźć właściwego sposobu, aby to zrobić.

 5
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-14 20:56:26

Chciałem tylko podłączyć się do wszelkich żądań ajax dla całej strony. @ Supergigant Oto z czym skończyłem:

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

Chciałem dokładnie sprawdzić niektóre kody statusu http, aby oprzeć swoją decyzję. Jednak można po prostu związać się z ajaxError, aby uzyskać coś innego niż sukces(może tylko 200?) Mogłem po prostu napisać:

$('body').bind('ajaxError', function(event,request,settings){
    window.location.replace("http://mysite.tld/login");
}
 5
Author: Bretticus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-04 18:47:29

Jeśli chcesz również przekazać wartości, możesz również ustawić zmienne sesji i dostęp Eg: W jsp możesz napisać

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

A następnie możesz zapisać tę wartość temp W Zmiennej javascript i bawić się

 5
Author: karthik339,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-07 06:35:28

Nie odniosłem żadnego sukcesu z rozwiązaniem nagłówka - nigdy nie zostały odebrane w mojej metodzie ajaxSuccess / ajaxComplete. Użyłem odpowiedzi Stega z custom response, ale zmodyfikowałem trochę stronę JS. Ustawiam metodę, którą wywołuję w każdej funkcji, aby móc używać standardowych metod $.get i $.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);
    }
}

Przykład tego w użyciu...

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
Author: jocull,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-06 13:45:02

W końcu rozwiązuję problem dodając własny HTTP Header. Tuż przed odpowiedzią na każde żądanie po stronie serwera dodaję aktualny żądany adres url do nagłówka odpowiedzi.

Mój typ aplikacji na serwerze to Asp.Net MVC i ma do tego dobre miejsce. w Global.asax zaimplementowałem Zdarzenie Application_EndRequest tak:

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

    }

To działa idealnie dla mnie! Teraz w każdej odpowiedzi JQuery $.post mam żądane url, a także inne nagłówki odpowiedzi, które pochodzą z metody POST według statusu 302, 303 ,... .

I inne ważne jest to, że nie ma potrzeby modyfikowania kodu po stronie serwera ani po stronie klienta.

A następna jest możliwość uzyskania dostępu do innych informacji o post akcji takich błędów, wiadomości i ... W ten sposób.

Zamieściłem to, może komuś pomóc:)

 5
Author: Ali Adlavaran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-30 06:02:24

Miałem ten problem na aplikacji django, z którą majstrowałem(zastrzeżenie: majstruję, aby się uczyć i w żaden sposób nie jestem ekspertem). To, co chciałem zrobić, to użyć jQuery ajax, aby wysłać żądanie usunięcia do zasobu, usunąć go po stronie serwera, a następnie wysłać przekierowanie z powrotem do (zasadniczo) strony głównej. Kiedy wysłałem HttpResponseRedirect('/the-redirect/') ze skryptu Pythona, metoda ajax jQuery otrzymywała 200 zamiast 302. Więc, co zrobiłem, to wysłałem odpowiedź 300 z:

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

Następnie wysłałem / załatwiłem prośbę na kliencie z jQuery.ajax tak:

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

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

Może używanie 300 nie jest "właściwe", ale przynajmniej działało tak, jak chciałem.

PS: To był ogromny ból edytować na mobilnej wersji SO. Głupi ISP złożył moją prośbę o anulowanie usługi, kiedy skończyłem z moją odpowiedzią!

 4
Author: Benny Jobigan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-28 10:18:14

Możesz również podłączyć XMLHttpRequest send prototype. Będzie to działać dla wszystkich wysyłanych (jQuery / dojo / etc) z jedną obsługą.

Napisałem ten kod, aby obsłużyć 500-stronicowy błąd wygasł, ale powinien działać równie dobrze, aby przechwycić przekierowanie 200. Przygotuj wpis Wikipedii na XMLHttpRequest onreadystatechange o znaczeniu 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
Author: Curtis Yallop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-10 19:38:59

Dodatkowo prawdopodobnie będziesz chciał przekierować użytkownika na podany w nagłówkach URL. Więc w końcu będzie to wyglądało tak:

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

UPD: Opps. Mają to samo zadanie, ale to nie działa. Robiąc takie rzeczy. Pokażę Ci rozwiązanie, kiedy je znajdę.

 1
Author: Vladimir Prudnikov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-19 11:13:33

Mam działający solulion używając odpowiedzi od @ John i @ Arpad link i @ RobWinch link

Używam Spring Security 3.2.9 i jQuery 1.10.2.

Rozszerz klasę Springa, aby powodować odpowiedź 4XX tylko z żądań 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-bezpieczeństwo.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>

W moim JSPs dodaj globalną obsługę błędów AJAX, jak pokazano tutaj

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

Usuń również istniejące procedury obsługi błędów z wywołań AJAX w JSP strony:

        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");
//            }
        });
Mam nadzieję, że to pomoże innym.

Update1 Okazało się, że muszę dodać opcję (always-use-default-target="true") do konfiguracji formularza-login. Było to potrzebne, ponieważ po przekierowaniu żądania AJAX na stronę logowania (z powodu wygasłej sesji), Spring zapamiętuje poprzednie żądanie AJAX i automatycznie przekierowuje do niego po zalogowaniu. Powoduje to wyświetlenie zwracanego pliku JSON na stronie przeglądarki. Oczywiście, nie to co ja chcę.

Update2 Zamiast używać always-use-default-target="true", Użyj @RobWinch przykład blokowania żądań AJAX z requstCache. Dzięki temu normalne linki mogą być przekierowywane do ich pierwotnego celu po zalogowaniu, ale AJAX przejść do strony głównej po zalogowaniu.

 0
Author: Darren Parker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-26 18:51:57