62 votes

Rails ne recharge pas la session lors d'un post ajax

Je rencontre un problème très étrange avec Rails et ajax en utilisant jQuery (bien que je ne pense pas que ce soit spécifique à jQuery).

Mon application Rails utilise le magasin de session des cookies, et j'ai un login très simple qui définit l'identifiant de l'utilisateur dans la session. Si l'ID utilisateur n'est pas défini dans la session, l'application redirige vers une page de connexion. Cela fonctionne sans problème. Les requêtes JQuery GET fonctionnent bien aussi. Le problème est que lorsque je fais une requête POST jQuery, le navigateur envoie le cookie de session sans problème (je l'ai confirmé avec Firebug et en vidant request.cookies dans le journal) mais la session est vide, c'est-à-dire que la session est {}.

Je fais ça dans mon application.js :

$(document).ajaxSend(function(e, xhr, options) {
  var token = $("meta[name='csrf-token']").attr('content');
  xhr.setRequestHeader('X-CSRF-Token', token);
});

et voici mon exemple de poste :

$.post('/test/1', { _method: 'delete' }, null, 'json');

qui doit aboutir à cette méthode du contrôleur (_method : delete) :

def destroy
  respond_to do |format|
    format.json { render :json => { :destroyed => 'ok' }.to_json }
  end
end

En regardant le journal et en utilisant Firebug, je peux confirmer que la valeur correcte du cookie est envoyée dans l'en-tête de la requête lorsque le post ajax se produit, mais il semble qu'à un moment donné, Rails perde cette valeur et donc la session, de sorte qu'il redirige vers la page de connexion et n'arrive jamais à la méthode.

J'ai essayé tout ce que j'ai pu imaginer pour déboguer ce problème, mais je commence à penser qu'il s'agit peut-être d'un bug de Rails. J'utilise Rails 3.0.4 et jQuery 1.5 si cela peut aider. Je trouve très étrange que les requêtes get et post normales (c'est-à-dire sans ajax) fonctionnent, que les requêtes get ajax fonctionnent sans problème, mais que les posts ajax ne fonctionnent pas.

Toute aide pour tenter de résoudre ce problème serait grandement appréciée !

Merci beaucoup,
Dave

114voto

fishwebby Points 1971

Je vais répondre à ma propre question car j'ai réussi à comprendre ce qui se passait. Je vais la poster ici au cas où elle serait utile à quelqu'un d'autre !

Après avoir enquêté davantage, j'ai découvert que le code qui était supposée pour mettre l'en-tête de la requête avec le jeton CSRF, ne l'était pas. C'était le code original :

$(document).ajaxSend(function(e, xhr, options) {
  var token = $("meta[name='csrf-token']").attr('content');
  xhr.setRequestHeader('X-CSRF-Token', token);
});

Ce qui se passait, c'est que ce code ne définissait pas l'en-tête, que Rails recevait une requête Ajax, que le jeton ne correspondait pas et que la session était réinitialisée. Avant, cela provoquait une erreur ActionController::InvalidAuthenticityToken (je suppose que j'aurais pu m'en rendre compte plus tôt si une erreur avait été provoquée... et bien), mais depuis Rails 3.0.4, cela réinitialise simplement la session.

Donc pour envoyer le jeton dans l'en-tête, vous devez faire ceci (merci beaucoup à ce merveilleux billet de blog ):

$.ajaxSetup({
  beforeSend: function(xhr) {
    xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
  }
}); 

Et maintenant, tout fonctionne comme il se doit. Ce qui est bien.

6voto

Siwei Shen Points 5814

J'ai trouvé une autre affaire :

Avez-vous défini la balise "csrf_meta_tag" dans le fichier de présentation de votre application ?

dans mon cas, je n'ai pas mis cette balise, et j'ai rencontré le même problème que vous.

Et après avoir défini la balise csrf_meta_tag dans app/views/layouts/application.html.erb, tout fonctionne bien !

Enfin, merci de m'avoir aidé à trouver la cause première ! Merci beaucoup ~

0voto

TheDeadSerious Points 580

C'est ce que le adaptateur rails officiel jquery-ujs est pour la série 3.0. Vous devez cependant vous souvenir de le maintenir à jour lorsque vous mettez à niveau les versions de rails.

Pour moi, la mise à jour de la version 3.0.3 à la version 3.0.8.rc4 impliquait également la récupération manuelle de l'adresse de l'utilisateur. src/rails.js à partir du répertoire lié.

Depuis que Rails 3.1 a finalement adopté jQuery, les choses devraient se mettre à jour automatiquement à l'avenir via la gemme jquery-rails lors de la mise à jour de rails (et en utilisant le pipeline d'actifs intégré de 3.1).

0voto

Ken H Points 311

Si vous avez toujours un problème après avoir envoyé csrf_meta_tag correctement au serveur. Assurez-vous que la configuration de votre magasin de session est correcte.

Si le :secure est définie comme vraie dans votre session_store.rb le cookie (session) ne sera pas transmis à votre serveur http. docs : https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html

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