web-dev-qa-db-fra.com

Rails ne rechargeant pas la session sur un post ajax

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

Mon application Rails utilise le magasin de sessions de cookies, et j’ai un identifiant de connexion 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, il est redirigé vers une page de connexion. Cela fonctionne sans problèmes. Les requêtes JQuery GET fonctionnent également très bien. Le problème, c’est lorsque je fais un jQuery POST - le navigateur envoie le cookie de session ok (je l’ai confirmé avec Firebug et dumping.cookies dans le journal), mais la session est vide, c’est-à-dire que la session est {}.

Je le fais 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 message:

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

qui devrait arriver à cette méthode de 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 la publication ajax se produit, mais il semble qu'à un moment donné, Rails perd cette valeur et perd donc la session, il est donc redirigé vers la connexion. page et n'arrive jamais à la méthode.

J'ai tout essayé pour résoudre ce problème, mais je commence à penser qu'il pourrait s'agir d'un bug dans Rails. J'utilise Rails 3.0.4 et jQuery 1.5 si cela aide. Je trouve très étrange que les demandes d’obtention et de publication régulières (c’est-à-dire non ajax) fonctionnent, et que les demandes d’ajax obtiennent un travail sans problèmes, ce sont simplement les publications ajax qui ne fonctionnent pas.

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

Merci beaucoup,
Dave

60
Dave Hollingworth

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

Après des recherches plus poussées, j’ai découvert que le code qui était supposé définir l’en-tête de la demande 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'était que ce code ne définissait pas l'en-tête, Rails recevait une demande Ajax, le jeton ne correspondait pas et il réinitialisait la session. Cela permettait généralement de générer une erreur ActionController :: InvalidAuthenticityToken (je suppose que je l'aurais déjà saisie plus tôt si une erreur était générée ... ah bon), mais depuis Rails 3.0.4, il réinitialise maintenant la session en silence.

Donc, pour envoyer le jeton dans l'en-tête, vous devez le faire (merci beaucoup à ce merveilleux article 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. Qui est Nice.

113
Dave Hollingworth

J'ai trouvé un autre cas: 

avez-vous défini le 'csrf_meta_tag' dans le fichier de présentation de votre application?  

dans mon cas, je n'ai pas défini cette balise et j'ai rencontré le même problème avec le vôtre.

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

Enfin, merci de m'aider à trouver la cause fondamentale! merci beaucoup ~ 

5

C’est ce à quoi sert l’adaptateur officiel jquery-ujs Rails de la série 3.0. Vous devez cependant vous rappeler de le garder à jour lors de la mise à niveau des versions de Rails.

Pour moi, passer de 3.0.3 à 3.0.8.rc4 signifiait également extraire manuellement le fichier src/Rails.js à partir du référentiel lié.

Depuis que Rails 3.1 est finalement passé à jQuery, la mise à jour automatique devrait se faire via la gem jquery-Rails lors de la mise à jour de Rails (et de l'utilisation du pipeline d'actifs intégré de 3.1).

0
TheDeadSerious