Comment gérer une demande de redirection après un appel Ajax jQuery
Je suis en utilisant $.post()
à l'appel d'un servlet utilisant Ajax, puis en utilisant le HTML résultant fragment de remplacer un div
élément dans le courant de l'utilisateur page. Toutefois, si la fin de la session, le serveur envoie une redirection directive pour envoyer l'utilisateur vers la page de connexion. Dans ce cas, jQuery est le remplacement de la div
élément avec le contenu de la page de connexion, forçant les yeux de l'utilisateur d'être témoin d'une rare scène, en effet.
Comment puis-je gérer une directive redirect à partir d'un appel Ajax avec jQuery 1.2.6?
- (pas de réponse en tant que telle) - j'ai fait cela dans le passé par l'édition de la bibliothèque jquery et l'ajout d'une case de la page de connexion sur chaque XHR complète. Pas la meilleure solution car elle doit être effectuée à chaque fois que vous mettez à niveau, mais il n'résoudre le problème.
- Voir question à ce sujet: stackoverflow.com/questions/5941933/...
- Le
HttpContext.Response.AddHeader
et vérifier à ajaxsetup le succès est le chemin à parcourir - Pourquoi je ne peux pas le serveur retourne 401? Dans ce cas, vous pouvez avoir un global $.ajaxSetup et utiliser le code d'état de rediriger la page.
- ce lien doanduyhai.wordpress.com/2012/04/21/... donne moi la bonne solution
Vous devez vous connecter pour publier un commentaire.
J'ai lu cette question et mis en œuvre l'approche qui a été dit concernant le réglage du code d'état de réponse à 278 afin d'éviter le navigateur de façon transparente de la manipulation de la redirection. Même si cela a fonctionné, j'ai été un peu mécontent que c'est un peu un hack.
Après plus de creuser autour, j'ai abandonné cette approche et JSON. Dans ce cas, toutes les réponses aux requêtes ajax avoir le code d'état 200 et le corps de la réponse contient un objet JSON qui est construit sur le serveur. Le javascript sur le client peut alors utiliser l'objet JSON de décider ce qu'il doit faire.
J'ai eu un problème similaire au vôtre. J'ai effectuer une requête ajax qui a 2 réponses possibles: l'une qui redirige le navigateur vers une nouvelle page, et celui qui remplace un formulaire HTML sur la page en cours avec un nouveau. Le jquery, le code pour faire cela ressemble à quelque chose comme:
L'objet JSON "données" est construit sur le serveur pour avoir 2 membres: les données.redirection et de données.forme. J'ai trouvé cette approche à être beaucoup mieux.
J'ai résolu ce problème par:
L'ajout d'un en-tête personnalisé pour la réponse:
La liaison d'une fonction JavaScript pour la
ajaxSuccess
de l'événement et de la vérification pour voir si l'en-tête existe:location.reload();
que notre modèle de rediriger vers une autre autorisation de site.Global.asax
. DansApplication_AuthenticateRequest
événementPas les navigateurs poignée 301 et 302 réponses correctement. Et, en fait, la norme dit même qu'ils doivent les gérer de façon "transparente" qui est un ÉNORME casse-tête pour la Bibliothèque Ajax fournisseurs. Dans Ra-Ajax nous avons été obligés d'utiliser de statut de la réponse HTTP du code 278 (juste quelques "inutilisé" code de réussite) pour gérer de manière transparente les redirections à partir du serveur...
Cela me gêne vraiment, et si quelqu'un ici en "pull" dans le W3C j'apprécierais que vous pourriez laisser W3C savoir que nous avons vraiment besoin de gérer 301 et 302 codes de nous-mêmes...! 😉
La solution qui a finalement été mis en œuvre a été d'utiliser un wrapper pour la fonction de rappel de l'appel Ajax et dans ce wrapper de vérifier l'existence d'un élément spécifique sur le code HTML renvoyé morceau. Si l'élément a été trouvé, alors le wrapper exécuté une redirection. Si pas, le wrapper transmis l'appel à la réelle fonction de rappel.
Par exemple, notre fonction wrapper était quelque chose comme:
Puis, lors de la prise de l'appel Ajax, nous avons utilisé quelque chose comme:
Cela a fonctionné pour nous, parce que tous les appels Ajax toujours retourné HTML à l'intérieur d'un élément DIV qui nous utiliser pour remplacer une pièce de la page. Aussi, nous avons seulement besoin de rediriger vers la page de connexion.
J'aime Timmerz de la méthode avec une légère torsion de citron. Si jamais vous avez retourné contentType de texte/html lorsque vous êtes enceinte JSON, vous êtes plus susceptibles d'être redirigé. Dans mon cas, je viens de recharger la page, et il obtient redirigé vers la page de connexion. Oh, et vérifier que le jqXHR statut est de 200, ce qui semble idiot, parce que vous êtes dans la fonction d'erreur, non? Sinon, légitime en cas d'erreur va forcer un processus itératif de rechargement (oups)
Utiliser le faible niveau
$.ajax()
appel:Essayez ceci pour une redirection:
Je voulais juste partager mon approche, car cela pourrait cela pourrait aider quelqu'un:
En gros, j'ai inclus un module JavaScript qui s'occupe de l'authentification des trucs comme l'affichage du nom d'utilisateur et aussi ce cas de la manipulation de la rediriger vers la page de connexion.
Mon scénario: Nous avons un serveur ISA dans entre qui est à l'écoute de toutes les demandes et répond avec un 302 et un en-tête location sur notre page de connexion.
Dans mon JavaScript module de mes approche initiale était quelque chose comme
Le problème (comme beaucoup ici déjà mentionné plus haut), c'est que le navigateur gère la redirection par lui-même c'est pourquoi mon
ajaxComplete
rappel ai jamais appelé, mais à la place j'ai eu le réponse de la déjà redirigé page de Connexion qui était à l'évidence unstatus 200
. Le problème: comment détecter si le succès de 200 de réponse est de votre page de connexion ou les quelques autres arbitraire page??La solution
Puisque je n'étais pas en mesure de capturer de redirection 302 réponses, j'ai ajouté un
LoginPage
en-tête sur ma page de connexion qui contenait l'url de la page de connexion elle-même. Dans le module, j'ai maintenant l'écouter pour l'en-tête et de faire une redirection:...et qui fonctionne comme un charme :). Vous pourriez vous demander pourquoi je inclure l'url dans la
LoginPage
- tête...eh bien en fait, car je n'ai trouvé aucun moyen de déterminer l'url deGET
résultant de la localisation automatique de redirection à partir de l'xhr
objet...X-
, donc un mieux-tête à utiliser seraitX-LoginPage: http://example.com/login
.X-
.Je sais que ce sujet est vieux, mais je vais vous donner encore une autre approche que j'ai trouvé et décrit précédemment ici. Fondamentalement, je suis à l'aide d'ASP.MVC avec WIF (mais ce n'est pas vraiment important pour le contexte de ce sujet - réponse est adéquate de n'importe laquelle des cadres sont utilisés. L'indice reste inchangé - traitant de questions liées à des échecs d'authentification lors de l'exécution de requêtes ajax).
L'approche présentée ci-dessous s'applique à toutes les requêtes ajax hors de la boîte (s'ils ne sont pas à redéfinir beforeSend cas évidemment).
Avant toute requête ajax est effectuée
CheckPulse
méthode est invoquée (la méthode de contrôleur qui peut être rien de plus simple):Si l'utilisateur n'est pas authentifié (jeton a expiré), cette méthode ne peut pas être consulté (protégé par
Authorize
attribut). Parce que le framework gère l'authentification, tandis que l'expiration de ce jeton, il met code http 302 pour la réponse. Si vous ne voulez pas que votre navigateur pour gérer 302 réponse de manière transparente, de l'attraper dans la Mondial.asax et le changement de statut de la réponse - par exemple à 200 OK. En outre, ajouter un en-tête, qui vous demande de processus de réponse à façon (plus tard, à la côté client):Enfin sur le côté client de vérifier les en-tête personnalisé. Si aujourd'plein de redirection de page d'ouverture de session doit être fait (dans mon cas
window.location
est remplacé par l'url de demande qui est géré automatiquement par mon cadre).Je pense qu'une meilleure façon de gérer cela est de tirer parti de l'existant protocole HTTP codes de réponse, plus précisément
401 Unauthorized
.Voici comment je l'ai résolu:
Côté Client: se Lier à l'ajax événements
IMO c'est plus générique et que vous n'êtes pas à écrire quelques nouvelles spécifications personnalisées/en-tête. Vous aussi vous ne devriez pas avoir à modifier un de vos appels ajax.
Edit: Par @Rob commentaire ci-dessous, 401 (le code de statut HTTP pour les erreurs d'authentification) devrait être l'indicateur. Voir 403 Forbidden vs 401 non autorisé des réponses HTTP pour plus de détails. Cela étant dit, certains frameworks web utiliser 403 pour l'authentification ET de l'autorisation d'erreurs - donc s'adapter en conséquence. Merci Rob.
J'ai résolu ce problème comme ceci:
Ajouter un intergiciel pour le processus de réponse, si c'est une redirection pour une requête ajax, modifier la réponse à une réponse normale avec l'url de redirection.
Puis dans ajaxComplete, si la réponse contient redirection, elle doit être une redirection, donc changer la localisation du navigateur.
La plupart des solutions proposées comme l'utilisation d'une solution de contournement, à l'aide d'un en-tête supplémentaire ou un inappropiate code HTTP. Ces solutions, plus probablement, des travaux mais se sentir un peu "hacky'. J'ai trouvé une autre solution.
Nous utilisons WIF qui est configuré pour rediriger (passiveRedirectEnabled="true") sur une réponse 401. La redirection est utile lors de la manipulation normale de la demande, mais ne fonctionnera pas pour les requêtes AJAX (depuis les navigateurs ne pas exécuter l'302/redirect).
En utilisant le code suivant dans votre global.asax vous pouvez désactiver la redirection de requêtes AJAX:
Cela vous permet de retourner les réponses 401 pour les requêtes AJAX, qui javascript de votre pouvez alors gérer par le rechargement de la page. Le rechargement de la page de jeter un 401, qui seront traitées par WIF (et WIF redirige l'utilisateur vers la page de connexion).
Un exemple javascript pour gérer les erreurs 401:
Une autre solution que j'ai trouvé (particulièrement utile si vous souhaitez définir un comportement global) est d'utiliser la
$.ajaxsetup()
méthode avec lestatusCode
de la propriété. Comme d'autres l'ont souligné, ne pas utiliser une redirection statuscode (3xx
), au lieu d'utiliser un4xx
statuscode et gérer la redirection côté client.Remplacer
400
avec le statuscode vous souhaitez gérer. Comme déjà mentionné401 Unauthorized
pourrait être une bonne idée. J'utilise le400
puisqu'elle est très imprécise et je peux utiliser le401
pour des cas plus spécifiques (comme mauvais identifiants de connexion). Donc, au lieu de rediriger directement votre backend doit retourner un4xx
code-erreur lors de la session a expiré et vous vous gérer la redirection côté client. Fonctionne parfaitement pour moi, même avec des frameworks comme backbone.jsCe problème peut apparaître puis à l'aide de ASP.NET MVC RedirectToAction méthode. Pour prévenir la forme de l'affichage de la réponse de la div, vous pouvez simplement faire une sorte d'ajax filtre à réponse pour incomming réponses avec $.ajaxSetup. Si la réponse contient MVC de redirection, vous pouvez évaluer cette expression sur JS côté. Exemple de code pour JS ci-dessous:
Si des données sont: "de la fenêtre.location = '/Account/Login'" ci-dessus, le filtre de capture et d'évaluer de faire de la redirection au lieu de laisser les données à afficher.
data
est dans le corps de la réponse ou de l'en-tête?Mettre ensemble ce que Vladimir Prudnikov et Thomas Hansen a dit:
Dans django:
Cela rend le navigateur traiter la réponse comme un succès, et le remettre à votre Javascript.
J'ai une solution simple qui fonctionne pour moi, pas de serveur de changement de code nécessaire...il suffit d'ajouter une cuillère à café de noix de muscade...
- Je vérifier la présence de la balise html, mais vous pouvez changer la indexOf à la recherche de ce chaîne unique existe dans votre page de connexion...
Essayer
Mettre sur la page de connexion. Si il a été chargé dans une div sur la page principale, il sera rediriger jusqu'à la page de connexion. "#site" est un id d'une balise div qui est situé sur toutes les pages sauf la page de connexion.
J'ai résolu ce problème en mettant le suivant dans mon login.php page.
Alors que les réponses semblent travailler pour les gens si vous êtes à l'aide de la Sécurité Printemps, j'ai trouvé l'extension de LoginUrlAuthenticationEntryPoint et l'ajout de code spécifique pour gérer AJAX plus robuste. La plupart des exemples d'intercepter tous redirige pas seulement des échecs d'authentification. Ce n'est pas souhaitable pour le projet que je travaille sur. Vous pouvez trouver le besoin de prolonger ExceptionTranslationFilter et remplacer le "sendStartAuthentication" méthode pour supprimer la mise en cache étape si vous ne voulez pas l'échec de la requête AJAX mis en cache.
Exemple AjaxAwareAuthenticationEntryPoint:
Sources:
Un, Deux
Permettez-moi de citer à nouveau le problème tel que décrit par @Steg
À mon humble avis c'est un vrai défi, et sera officiellement étendu aux normes HTTP actuelles.
Je crois que le nouveau Http Norme sera d'utiliser un nouveau code.
sens: à l'heure actuelle
301/302
indique au navigateur d'aller chercher le contenu de ce demande à un nouveaulocation
.Dans le standard étendu, on va dire que si la réponse
status: 308
(juste un exemple), alors le navigateur de rediriger la page principale de lalocation
fourni.Cela étant dit, je suis enclin à déjà imiter cette avenir comportement, et, par conséquent, lorsqu'un document.redirection est nécessaire, j'ai le serveur de répondre:
Lors de la JS obtient le "
status: 204
", il vérifie l'existence de lax-status: 308
en-tête, et un document.redirection vers la page prévue dans lelocation
en-tête.Est-ce que cela a du sens pour vous?
Certains pourraient trouver ci-dessous l'utile:
Je voulais clients pour être redirigé vers la page de connexion de tout repos-action qui est envoyé en l'absence d'un jeton d'autorisation. Puisque l'ensemble de mon repos-les actions sont basé sur Ajax, j'ai besoin d'une bonne façon générique pour rediriger vers la page de connexion au lieu de la manipulation de l'Ajax succès fonction.
C'est ce que j'ai fait:
Sur toute requête Ajax mon serveur sera de retour Json 200 réponse "authentification" (si le client a besoin de s'authentifier).
Exemple Simple en Java (côté serveur):
Dans mon Javascript j'ai ajouté le code suivant:
Et c'est à ce sujet.
dans la servlet, vous devriez mettre
response.setStatus(response.SC_MOVED_PERMANENTLY);
envoyer le '301' xmlHttp statut dont vous avez besoin pour une redirection...
et dans l' $.ajax fonction, vous ne devez pas utiliser le
.toString()
fonction..., justeif (xmlHttp.status == 301) {
top.location.href = 'xxxx.jsp';
}
le problème est qu'il n'est pas très souples, vous ne pouvez pas décider de l'endroit où vous souhaitez rediriger..
de déviation par les servlets doivent être de la meilleure manière. mais j'arrive toujours pas à trouver la bonne façon de le faire.
Je voulais juste de s'accrocher à toutes les requêtes ajax pour l'ensemble de la page. @SuperG m'ont commencé. Voici ce que j'ai:
Je voulais contrôler spécifiquement certains codes de statut http de la base de ma décision. Toutefois, vous pouvez simplement lier à ajaxError d'obtenir autre chose que le succès (200 seulement peut-être?) Je pourrais avoir juste écrit:
Si vous aussi vous voulez transmettre les valeurs, alors vous pouvez aussi définir les variables de session et d'accès
Par exemple:
Dans votre jsp, vous pouvez écrire
Et puis vous pouvez enregistrer ce temp la valeur de votre variable javascript et jouer autour de
Je n'ai pas de succès avec l'en-tête de la solution - ils n'ont jamais été ramassé dans mon ajaxSuccess /ajaxComplete méthode. J'ai utilisé de la Steg, en réponse à la coutume de réponse, mais j'ai modifié la JS côté quelques. J'ai installé une méthode que j'appelle dans chaque fonction, donc je peux utiliser des
$.get
et$.post
méthodes.Exemple dans l'utilisation...
Enfin, je résoudre le problème en ajoutant une coutume
HTTP Header
. Juste avant réponse pour chaque requête au serveur, j'ai ajouter une url demandée à la réponse de l'en-tête.Mon type d'application sur le serveur est
Asp.Net MVC
, et il a un bon endroit pour le faire. dansGlobal.asax
j'ai mis en place leApplication_EndRequest
événement:Il fonctionne parfaitement pour moi! Maintenant à chaque réponse de l'
JQuery
$.post
j'ai demandéurl
et aussi d'autres en-têtes de réponse qui est le résultat de laPOST
méthode par statut302
,303
,... .et l'autre chose importante est qu'il n'est pas nécessaire de modifier le code côté serveur, ni du côté client.
et la prochaine est la capacité à obtenir l'accès à d'autres informations d'action post de telles erreurs, les messages, et ..., De cette façon.
J'ai posté ceci, peut-être aider quelqu'un 🙂
J'ai eu ce problème sur un django app je suis à bricoler (disclaimer: je suis bricolage pour apprendre, et je suis en aucun cas un expert). Ce que je voulais faire était d'utiliser jQuery ajax pour envoyer une demande de SUPPRESSION d'une ressource, de le supprimer sur le serveur de l'autre côté, puis envoyer une demande de redirection (en gros) la page d'accueil. Quand j'ai envoyé
HttpResponseRedirect('/the-redirect/')
à partir du script python, jQuery ajax méthode a été la réception de 200 au lieu de 302. Donc, ce que j'ai fait a été d'envoyer une réponse de 300 avec:Puis j'ai envoyé/traité de la demande sur le client avec jQuery.ajax comme suit:
Peut-être à l'aide de 300 n'est pas "de droite", mais au moins il a fonctionné comme je le voulais.
PS :c'était une énorme douleur à modifier sur la version mobile de la SORTE. Stupide FAI de mettre mes service de demande d'annulation par le droit quand j'ai eu terminé ma réponse!
Vous pouvez également brancher XMLHttpRequest envoyer prototype. Cela fonctionne pour tous les départs (jQuery/dojo/etc) avec un seul gestionnaire.
J'ai écrit ce code pour gérer un 500 page expiré erreur, mais cela fonctionne tout aussi bien pour piéger un de 200 de redirection. Préparer l'entrée de wikipedia sur XMLHttpRequest onreadystatechange sur le sens de la readyState.
En outre, vous voudrez probablement pour rediriger les utilisateurs de la donnée dans les en-têtes URL. Donc, finalement, il ressemble à ceci:
UPD: Opps. La même tâche, mais il ne fonctionne. Faire ce genre de choses. Je vais vous montrer la solution quand je vais le trouver.
J'ai eu une solulion de travail en utilisant les réponses de @John et @Arpad lien et @RobWinch lien
- Je utiliser de la Sécurité Printemps 3.2.9 et jQuery 1.10.2.
Étendre le Printemps de la classe à cause 4XX réponse seulement pour les requêtes AJAX:
applicationContext-security.xml
Dans ma Jsp, ajouter un global AJAX gestionnaire d'erreur comme indiqué ici
Aussi, supprimer les gestionnaires d'erreur à partir des appels AJAX dans les pages JSP:
J'espère que cela aide les autres.
Update1
J'ai trouvé que j'ai besoin d'ajouter l'option (toujours utiliser-par défaut-target="true") pour le formulaire de connexion config.
C'était nécessaire, car après une requête AJAX obtient redirigé vers la page de connexion (dues à l'expiration de la session), le Printemps se souvient de la précédente requête AJAX et auto redirection après login. Cela provoque le retour JSON pour être affiché sur la page de votre navigateur. Bien sûr, pas ce que je veux.
Update2
Au lieu d'utiliser
always-use-default-target="true"
, utilisez @RobWinch exemple de bloquer les requêtes AJAX à partir de la requstCache. Cela permet à la normale de liens pour être redirigé vers leur objectif initial après la connexion, mais AJAX aller à la page d'accueil après connexion.cela a fonctionné pour moi:
en cas de succès, ajax obtiendrez le même code d'état du navigateur obtient à partir du serveur et de l'exécuter.