1480 votes

Comment gérer une demande de redirection après un appel Ajax de jQuery ?

J'utilise $.post() pour appeler une servlet à l'aide d'Ajax, puis en utilisant le fragment HTML résultant pour remplacer un fichier de type div dans la page actuelle de l'utilisateur. Toutefois, si la session expire, le serveur envoie une directive de redirection pour renvoyer l'utilisateur vers la page de connexion. Dans ce cas, jQuery remplace l'élément div avec le contenu de la page de connexion, obligeant les yeux de l'utilisateur à assister à une scène rare.

Comment gérer une directive de redirection à partir d'un appel Ajax avec jQuery 1.2.6 ?

1 votes

(pas une réponse en tant que telle) - J'ai fait cela dans le passé en modifiant la bibliothèque jquery et en ajoutant une vérification de la page de connexion à chaque XHR complet. Ce n'est pas la meilleure solution car il faudrait le faire à chaque mise à jour, mais cela résout le problème.

1 votes

Voir la question connexe : stackoverflow.com/questions/5941933/

0 votes

En HttpContext.Response.AddHeader et vérifier le succès d'ajaxsetup est la voie à suivre.

21voto

morten.c Points 1021

Une autre solution que j'ai trouvée (particulièrement utile si vous voulez définir un comportement global) est d'utiliser la fonction $.ajaxsetup() méthode avec le statusCode propriété . Comme d'autres l'ont souligné, n'utilisez pas un code de statut de redirection ( 3xx ), utilisez plutôt un 4xx et traiter la redirection côté client.

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

Remplacer 400 avec le code d'état que vous voulez traiter. Comme déjà mentionné 401 Unauthorized pourrait être une bonne idée. J'utilise le 400 puisqu'il n'est pas très spécifique et que je peux utiliser l'option 401 pour des cas plus spécifiques (comme des identifiants de connexion erronés). Ainsi, au lieu de rediriger directement, votre backend devrait renvoyer un message de type 4xx code d'erreur lorsque la session a expiré et que vous traitez la redirection côté client. Cela fonctionne parfaitement pour moi, même avec des frameworks comme backbone.js.

20voto

Timmerz Points 1235

J'ai une solution simple qui fonctionne pour moi, pas de changement de code de serveur nécessaire...il suffit d'ajouter une cuillère à café de noix de muscade....

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

Je vérifie la présence de la balise html, mais vous pouvez modifier l'indexOf pour rechercher toute chaîne unique existant dans votre page de connexion...

20voto

Rob Points 719

La plupart des solutions proposées utilisent une solution de contournement, en utilisant un en-tête supplémentaire ou un code HTTP inapproprié. Ces solutions fonctionneront très probablement, mais elles sont un peu "bricolées". J'ai trouvé une autre solution.

Nous utilisons le WIF qui est configuré pour rediriger (passiveRedirectEnabled="true") sur une réponse 401. La redirection est utile pour traiter les requêtes normales mais ne fonctionne pas pour les requêtes AJAX (puisque les navigateurs n'exécutent pas le 302/redirect).

En utilisant le code suivant dans votre global.asax, vous pouvez désactiver la redirection pour les demandes 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;
        }
    }

Cela vous permet de renvoyer des réponses 401 pour les demandes AJAX, que votre javascript peut alors traiter en rechargeant la page. Le rechargement de la page renverra une réponse 401 qui sera traitée par le WIF (et le WIF redirigera l'utilisateur vers la page de connexion).

Un exemple de javascript pour gérer les erreurs 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);
    }
});

19voto

Ce problème peut apparaître lors de l'utilisation de la méthode ASP.NET MVC RedirectToAction. Pour éviter que le formulaire affiche la réponse dans un div, vous pouvez simplement faire une sorte de filtre de réponse ajax pour les réponses incomminging avec $.ajaxSetup . Si la réponse contient une redirection MVC, vous pouvez évaluer cette expression du côté JS. Exemple de code pour JS ci-dessous :

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

Si les données le sont : "window.location = '/Acount/Login'" Le filtre ci-dessus le détectera et l'évaluera pour effectuer la redirection au lieu de laisser les données s'afficher.

17voto

Graham King Points 1295

En mettant ensemble ce que Vladimir Prudnikov et Thomas Hansen ont dit :

  • Modifiez votre code côté serveur pour détecter s'il s'agit d'un XHR. Si c'est le cas, définissez le code de réponse de la redirection à 278. Dans django :
   if request.is_ajax():
      response.status_code = 278

Cela permet au navigateur de traiter la réponse comme un succès et de la transmettre à votre Javascript.

  • Dans votre JS, assurez-vous que la soumission du formulaire se fait via Ajax, vérifiez le code de réponse et redirigez si nécessaire :
$('#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); 
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X