Używam $.post()
do wywołania serwletu za pomocą Ajax, a następnie używam wynikowego fragmentu HTML do zastąpienia div
elementu na bieżącej stronie użytkownika. Jeśli jednak upłynie limit czasu sesji, serwer wysyła dyrektywę przekierowania, aby wysłać użytkownika na stronę logowania. W tym przypadku jQuery zastępuje div
element zawartością strony logowania, zmuszając oczy użytkownika do zobaczenia naprawdę rzadkiej sceny.
Jak zarządzać dyrektywą przekierowującą z wywołania Ajax za pomocą jQuery 1.2.6?
javascript
jquery
ajax
redirect
Elliot Vargas
źródło
źródło
HttpContext.Response.AddHeader
I czek na ajaxsetup sukcesu jest do zrobieniaOdpowiedzi:
Przeczytałem to pytanie i wdrożyłem podane podejście dotyczące ustawiania kodu statusu odpowiedzi HTTP na 278, aby uniknąć przezroczystej obsługi przekierowań przez przeglądarkę. Mimo, że to zadziałało, byłem trochę niezadowolony, ponieważ jest to trochę hack.
Po dalszych poszukiwaniach porzuciłem to podejście i użyłem JSON . W takim przypadku wszystkie odpowiedzi na żądania AJAX mają kod statusu 200, a treść odpowiedzi zawiera obiekt JSON zbudowany na serwerze. JavaScript na kliencie może następnie użyć obiektu JSON, aby zdecydować, co musi zrobić.
Miałem podobny problem do twojego. Wykonuję żądanie AJAX, które ma 2 możliwe odpowiedzi: jedną, która przekierowuje przeglądarkę na nową stronę i jedną, która zastępuje istniejący formularz HTML na bieżącej stronie nową. Aby to zrobić, kod jQuery wygląda mniej więcej tak:
Obiekt „dane” JSON jest konstruowany na serwerze i ma 2 członków:
data.redirect
orazdata.form
. Uważam, że to podejście jest znacznie lepsze.źródło
Rozwiązałem ten problem przez:
Dodanie niestandardowego nagłówka do odpowiedzi:
Wiązanie funkcji JavaScript do
ajaxSuccess
zdarzenia i sprawdzenie, czy nagłówek istnieje:źródło
Żadna przeglądarka nie obsługuje poprawnie odpowiedzi 301 i 302. W rzeczywistości standard mówi nawet, że powinni obchodzić się z nimi „w sposób przejrzysty”, co jest MASYWNYM bólem głowy dla dostawców Biblioteki Ajax. W Ra-Ajaxie byliśmy zmuszeni używać kodu statusu odpowiedzi HTTP 278 (tylko trochę „nieużywanego” kodu sukcesu) do obsługi przezroczystych przekierowań z serwera ...
To mnie naprawdę denerwuje, a jeśli ktoś tutaj ma jakieś „przyciąganie” w W3C, byłbym wdzięczny, że możesz poinformować W3C , że naprawdę musimy sami obsługiwać kody 301 i 302 ...! ;)
źródło
Rozwiązaniem, które ostatecznie zostało wdrożone, było użycie opakowania dla funkcji wywołania zwrotnego wywołania Ajax, aw tym opakowaniu sprawdzenie, czy istnieje określony element na zwróconej porcji HTML. Jeśli element został znaleziony, opakowanie wykonało przekierowanie. Jeśli nie, opakowanie przekazuje połączenie do faktycznej funkcji oddzwaniania.
Na przykład nasza funkcja otoki wyglądała mniej więcej tak:
Następnie, wykonując wywołanie Ajax, użyliśmy czegoś takiego:
To działało dla nas, ponieważ wszystkie wywołania Ajax zawsze zwracały HTML wewnątrz elementu DIV, którego używamy do zastąpienia fragmentu strony. Musieliśmy również przekierować na stronę logowania.
źródło
Lubię metodę Timmerza z lekkim posmakiem cytryny. Jeśli kiedykolwiek wrócił contentType z text / html kiedy czekasz JSON , jesteś najprawdopodobniej przekierowany. W moim przypadku po prostu ponownie ładuję stronę i zostaje ona przekierowana na stronę logowania. Aha, i sprawdź, czy status jqXHR wynosi 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 (ups)
źródło
Użyj połączenia niskiego poziomu
$.ajax()
:Wypróbuj to dla przekierowania:
źródło
Chciałem tylko podzielić się moim podejściem, ponieważ może to pomóc komuś:
Zasadniczo załączyłem moduł JavaScript, który obsługuje uwierzytelnianie, takie jak wyświetlanie nazwy użytkownika, a także ta sprawa obsługująca przekierowanie na stronę logowania .
Mój scenariusz: Zasadniczo mamy serwer ISA, pomiędzy którym nasłuchuje wszystkich żądań i odpowiada 302 i nagłówkiem lokalizacji na naszej stronie logowania.
W moim module JavaScript moje początkowe podejście było podobne
Problem (jak już tu wspomniano) polega na tym, że przeglądarka sama obsługuje przekierowanie, dlatego moje
ajaxComplete
wywołanie zwrotne nigdy nie zostało wywołane, ale zamiast tego otrzymałem odpowiedź przekierowanej strony logowania, która oczywiście byłastatus 200
. Problem: jak wykryć, czy pomyślna odpowiedź 200 jest Twoją rzeczywistą stroną logowania, czy po prostu inną dowolną stroną?Rozwiązanie
Ponieważ nie byłem w stanie przechwycić 302 odpowiedzi przekierowań, dodałem
LoginPage
nagłówek na mojej stronie logowania, który zawierał adres URL samej strony logowania. W module teraz słucham nagłówka i wykonuję przekierowanie:... a to działa jak urok :). Możesz się zastanawiać, dlaczego umieszczam adres URL w
LoginPage
nagłówku ... cóż, zasadniczo dlatego, że nie znalazłem sposobu na określenieGET
adresu URL wynikającego z automatycznego przekierowania lokalizacji zxhr
obiektu ...źródło
X-
, więc lepiej byłoby użyć nagłówkaX-LoginPage: http://example.com/login
.X-
.Wiem, że ten temat jest stary, ale podam jeszcze jedno podejście, które znalazłem i poprzednio opisałem tutaj . Zasadniczo używam ASP.MVC z WIF (ale to nie jest tak naprawdę ważne w kontekście tego tematu - odpowiedź jest odpowiednia bez względu na to, jakie ramy są używane. Wskazówka pozostaje niezmieniona - radzenie sobie z problemami związanymi z błędami uwierzytelnienia podczas wykonywania żądań ajax ) .
Podejście pokazane poniżej może być zastosowane do wszystkich żądań ajax po wyjęciu z pudełka (jeśli nie przedefiniują one oczywiście przed wysyłaniem zdarzenia oczywiście).
Przed wykonaniem jakiegokolwiek żądania ajax
CheckPulse
wywoływana jest metoda (metoda kontrolera, która może być najprostsza):Jeśli użytkownik nie jest uwierzytelniony (token wygasł), dostęp do takiej metody nie jest możliwy (chroniony przez
Authorize
atrybut). Ponieważ środowisko obsługuje uwierzytelnianie, podczas gdy token wygasa, przekazuje on do odpowiedzi stan HTTP 302. Jeśli nie chcesz, aby twoja przeglądarka w sposób transparentny obsługiwała odpowiedź 302, złap ją w Global.asax i zmień status odpowiedzi - na przykład na 200 OK. Dodatkowo dodaj nagłówek, który instruuje Cię, aby przetworzyć taką odpowiedź w specjalny sposób (później po stronie klienta):Wreszcie po stronie klienta sprawdź niestandardowy nagłówek. Jeśli jest obecny - należy dokonać pełnego przekierowania na stronę logowania (w moim przypadku
window.location
zastępuje go adres URL z żądania, który jest obsługiwany automatycznie przez mój framework).źródło
Myślę, że lepszym sposobem na poradzenie sobie z tym jest wykorzystanie istniejących kodów odpowiedzi protokołu HTTP
401 Unauthorized
.Oto jak to rozwiązałem:
Po stronie klienta: powiązanie ze zdarzeniami ajax
IMO jest to bardziej ogólne i nie piszesz nowych niestandardowych specyfikacji / nagłówków. Nie powinieneś również modyfikować żadnych istniejących wywołań ajax.
Edycja: Według komentarza @ @ Rob poniżej 401 (kod stanu HTTP dla błędów uwierzytelnienia) powinien być wskaźnikiem. Aby uzyskać więcej informacji, zobacz 403 Zabronione vs 401 Nieautoryzowane odpowiedzi HTTP . Mając to na uwadze, niektóre frameworki internetowe używają 403 zarówno do błędów uwierzytelnienia, jak i autoryzacji - więc odpowiednio się dostosuj. Dzięki, Rob.
źródło
Rozwiązałem ten problem w następujący sposób:
Dodaj oprogramowanie pośrednie, aby przetworzyć odpowiedź, jeśli jest to przekierowanie dla żądania ajax, zmień odpowiedź na normalną odpowiedź za pomocą adresu URL przekierowania.
Następnie w ajaxComplete, jeśli odpowiedź zawiera przekierowanie, musi to być przekierowanie, więc zmień lokalizację przeglądarki.
źródło
Mam proste rozwiązanie, które działa dla mnie, nie trzeba zmieniać kodu serwera ... wystarczy dodać łyżeczkę gałki muszkatołowej ...
Sprawdzam obecność tagu HTML, ale możesz zmienić indexOf, aby wyszukać unikalny ciąg znaków na stronie logowania ...
źródło
Innym rozwiązaniem, które znalazłem (szczególnie przydatne, jeśli chcesz ustawić globalne zachowanie) jest użycie
$.ajaxsetup()
metody razem zstatusCode
właściwością . Jak zauważyli inni, nie używaj przekierowania statuscode (3xx
), zamiast tego użyj4xx
kodu statusu i obsłuż przekierowanie po stronie klienta.Zastąp
400
kod statusu, który chcesz obsłużyć. Jak już wspomniano,401 Unauthorized
może być dobrym pomysłem. Używam,400
ponieważ jest to bardzo niespecyficzne i mogę użyć401
do bardziej konkretnych przypadków (takich jak nieprawidłowe dane logowania). Zamiast przekierowywać bezpośrednio, backend powinien zwrócić4xx
kod błędu, gdy upłynie limit czasu sesji, a ty obsłużysz przekierowanie po stronie klienta. Działa idealnie dla mnie nawet z frameworkami takimi jak backbone.jsźródło
Większość podanych rozwiązań wykorzystuje obejście, dodatkowy nagłówek lub nieodpowiedni kod HTTP. Te rozwiązania najprawdopodobniej zadziałają, ale są nieco „hackerskie”. Wymyśliłem inne rozwiązanie.
Używamy WIF, który jest skonfigurowany do przekierowania (passiveRedirectEnabled = "true") w odpowiedzi 401. Przekierowanie jest przydatne podczas obsługi normalnych żądań, ale nie działa dla żądań AJAX (ponieważ przeglądarki nie wykonają przekierowania 302 /).
Za pomocą następującego kodu w pliku global.asax możesz wyłączyć przekierowanie dla żądań AJAX:
Umożliwia to zwrócenie 401 odpowiedzi na żądania AJAX, które następnie JavaScript może obsłużyć przez ponowne załadowanie strony. Przeładowanie strony wyrzuci 401, który będzie obsługiwany przez WIF (a WIF przekieruje użytkownika na stronę logowania).
Przykładowy javascript do obsługi błędów 401:
źródło
Ten problem może pojawić się wtedy przy użyciu metody RedirectToAction ASP.NET MVC. Aby zapobiec wyświetlaniu odpowiedzi w formularzu w formacie div, możesz po prostu zrobić filtr filtru odpowiedzi ajax dla przychodzących 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:
Jeśli dane to: „window.location = '/ Acount / Login'” powyżej filtr złapie to i oceni, aby dokonać przekierowania zamiast pozwolić na wyświetlanie danych.
źródło
data
jest w treści odpowiedzi lub nagłówku?Zestawiając to, co powiedzieli Władimir Prudnikow i Thomas Hansen:
To sprawia, że przeglądarka traktuje odpowiedź jako sukces i przekazuje ją skryptowi Javascript.
źródło
źródło
Próbować
Umieść go na stronie logowania. Jeśli został załadowany do div na stronie głównej, przekieruje do strony logowania. „#site” to identyfikator div, który znajduje się na wszystkich stronach oprócz strony logowania.
źródło
Podczas gdy odpowiedzi wydają się działać dla ludzi, jeśli korzystasz z Spring Security, znalazłem rozszerzenie LoginUrlAuthenticationEntryPoint i dodanie konkretnego kodu do obsługi AJAX bardziej niezawodnego. Większość przykładów przechwytuje wszystkie przekierowania, a nie tylko błędy uwierzytelnienia. Było to niepożądane w przypadku projektu, nad którym pracuję. Może być konieczne rozszerzenie ExceptionTranslationFilter i zastąpienie metody „sendStartAuthentication” w celu usunięcia kroku buforowania, jeśli nie chcesz buforować nieudanego żądania AJAX.
Przykład AjaxAwareAuthenticationEntryPoint:
Źródła: 1 , 2
źródło
Rozwiązałem ten problem, umieszczając następujące informacje na mojej stronie login.php.
źródło
Pozwól, że przytoczę jeszcze raz problem opisany przez @Steg
IMHO to prawdziwe wyzwanie i będzie musiało zostać oficjalnie rozszerzone na obecne standardy HTTP.
Wierzę, że nowy standard HTTP będzie używał nowego kodu statusu. co oznacza: obecnie
301/302
mówi przeglądarce, aby przejść i pobrać treść tego żądania do nowegolocation
.W rozszerzonym standardzie powie, że jeśli odpowiedź
status: 308
(tylko przykład), to przeglądarka powinna przekierować stronę główną dolocation
podanego.To powiedziawszy; Skłaniam się już do naśladowania tego przyszłego zachowania i dlatego, gdy potrzebny jest dokument document.redirect, serwer odpowiada:
Gdy JS otrzymuje „
status: 204
”, sprawdza istnieniex-status: 308
nagłówka i robi document.redirect do strony podanej wlocation
nagłówku.Czy to ma dla ciebie jakiś sens?
źródło
Niektóre mogą okazać się przydatne poniżej:
Chciałem, aby klienci zostali przekierowani na stronę logowania w celu wykonania dowolnej akcji odpoczynku wysłanej bez tokena autoryzacji. Ponieważ wszystkie moje akcje odpoczynku są oparte na Ajaxie, potrzebowałem dobrego ogólnego sposobu przekierowania na stronę logowania zamiast obsługi funkcji sukcesu Ajax.
Oto co zrobiłem:
Na każde żądanie Ajax mój serwer zwróci odpowiedź Jsona 200 „POTRZEBUJĘ AUTENTENTACJI” (jeśli klient musi się uwierzytelnić).
Prosty przykład w Javie (po stronie serwera):
W moim Javascript dodałem następujący kod:
I o to chodzi.
źródło
w serwletu należy umieścić,
response.setStatus(response.SC_MOVED_PERMANENTLY);
aby wysłać status „301” xmlHttp potrzebny do przekierowania ...a w funkcji $ .ajax nie powinieneś używać
.toString()
funkcji ..., tylkoif (xmlHttp.status == 301) { top.location.href = 'xxxx.jsp'; }
problem polega na tym, że nie jest zbyt elastyczny, nie możesz zdecydować, gdzie chcesz przekierować.
przekierowywanie przez serwlety powinno być najlepszym sposobem. ale nadal nie mogę znaleźć właściwego sposobu, aby to zrobić.
źródło
Chciałem po prostu zatrzasnąć wszystkie żądania ajaxowe dla całej strony. @ Superup mnie zaczął. Oto, z czym skończyłem:
Chciałem szczególnie sprawdzić niektóre kody stanu HTTP, na których opiera się moja decyzja. Jednak możesz po prostu powiązać z ajaxError, aby uzyskać coś innego niż sukces (może tylko 200?) Mógłbym właśnie napisać:
źródło
Jeśli chcesz również przekazać wartości, możesz także ustawić zmienne sesji i uzyskać dostęp np. W: JSP możesz pisać
Następnie możesz zapisać tę wartość temp w zmiennej javascript i bawić się
źródło
Nie miałem żadnego sukcesu z rozwiązaniem nagłówkowym - nigdy nie zostały one odebrane w mojej metodzie ajaxSuccess / ajaxComplete. Użyłem odpowiedzi Stega z niestandardową odpowiedzią, ale trochę zmodyfikowałem stronę JS. Ustawiam metodę, którą wywołuję w każdej funkcji, dzięki czemu mogę używać standardu
$.get
i$.post
metod.Przykład użycia ...
źródło
Wreszcie rozwiązuję problem, dodając niestandardowy
HTTP Header
. Tuż przed odpowiedzią na każde żądanie po stronie serwera dodaję bieżący żądany adres URL do nagłówka odpowiedzi.Mój typ aplikacji na serwerze jest
Asp.Net MVC
i jest na to dobre miejsce. wGlobal.asax
I wdrożoneApplication_EndRequest
zdarzenie tak:Działa idealnie dla mnie! Teraz w każdej odpowiedzi z
JQuery
$.post
mam żądanychurl
, a także inne nagłówki odpowiedzi, które przychodzi jako skutekPOST
sposobu według statusu302
,303
....a inną ważną rzeczą jest to, że nie ma potrzeby modyfikowania kodu po stronie serwera ani po stronie klienta.
a następną jest możliwość uzyskania dostępu do innych informacji dotyczących akcji post, takich jak błędy, wiadomości i ..., w ten sposób.
Wysłałem to, może komuś pomóc :)
źródło
Miałem ten problem w aplikacji django, którą majstruję (zastrzeżenie: majstruję, aby się uczyć i nie jestem w żaden sposób ekspertem). Chciałem użyć jQuery ajax, aby wysłać żądanie DELETE do zasobu, usunąć je po stronie serwera, a następnie wysłać przekierowanie z powrotem (w zasadzie) do strony głównej. Kiedy wysłałem
HttpResponseRedirect('/the-redirect/')
ze skryptu Pythona, metoda ajax jQuery'ego otrzymywała 200 zamiast 302. Tak więc, wysłałem odpowiedź 300 z:Następnie wysłałem / obsłużyłem żądanie na kliencie z jQuery.ajax w następujący sposób:
Może używanie 300 nie jest „właściwe”, ale przynajmniej działało tak, jak chciałem.
PS: edytowanie mobilnej wersji SO było bardzo trudne. Głupi usługodawca internetowy złożył moje żądanie anulowania usługi, kiedy skończyłem z moją odpowiedzią!
źródło
Możesz także podpiąć prototyp wysyłania XMLHttpRequest. Działa to dla wszystkich wysyłek (jQuery / dojo / etc) z jednym modułem obsługi.
Napisałem ten kod, aby obsłużyć błąd 500 stron, który wygasł, ale powinien działać równie dobrze, aby przechwycić przekierowanie 200. Przygotuj wpis w Wikipedii na XMLHttpRequest onreadystatzmień o znaczeniu readyState.
źródło
Dodatkowo prawdopodobnie będziesz chciał przekierować użytkownika do podanego w nagłówku adresu URL. W końcu będzie to wyglądać tak:
UPD: Opps. Miej to samo zadanie, ale to nie działa. Robienie tego. Pokażę ci rozwiązanie, kiedy je znajdę.
źródło
Mam solulion roboczą używając odpowiedzi od @John i @Arpad linku i @RobWinch linku
Używam Spring Security 3.2.9 i jQuery 1.10.2.
Rozszerz klasę Spring, aby powodować odpowiedź 4XX tylko z żądań AJAX:
applicationContext-security.xml
Do moich stron JSP dodaj globalną procedurę obsługi błędów AJAX, jak pokazano tutaj
Usuń także istniejące procedury obsługi błędów z wywołań AJAX na stronach JSP:
Mam nadzieję, że to pomaga innym.
Aktualizacja 1 Odkryłem , że muszę dodać opcję (always-use-default-target = "true") do konfiguracji formularza logowania. Było to potrzebne, ponieważ po przekierowaniu żądania AJAX do strony logowania (z powodu wygasłej sesji) Spring zapamiętuje poprzednie żądanie AJAX i automatycznie przekierowuje je po zalogowaniu. Powoduje to, że zwrócony JSON jest wyświetlany na stronie przeglądarki. Oczywiście nie to, czego chcę.
Update2 Zamiast używać
always-use-default-target="true"
, użyj przykładu @RobWinch blokowania żądań AJAX z requstCache. Umożliwia to przekierowanie zwykłych linków do ich pierwotnego celu po zalogowaniu, ale AJAX przechodzi do strony głównej po zalogowaniu.źródło