Rails没有在ajax帖子上重新加载会话

时间:2011-02-26 11:52:05

标签: ruby-on-rails ajax jquery

我正在使用jQuery遇到一个非常奇怪的Rails和ajax问题(虽然我不认为它特定于jQuery)。

My Rails应用程序使用cookie会话存储,我有一个非常简单的登录,在会话中设置用户ID。如果未在会话中设置user_id,则会重定向到登录页面。这没有问题。 JQuery GET请求也可以正常工作。问题是当我做一个jQuery POST时 - 浏览器发送会话cookie ok(我用Firebug确认了这个并将request.cookies转储到日志中)但会话是空白的,即session是{}。

我在我的application.js中执行此操作:

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

这是我的样本帖子:

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

应该使用这个控制器方法(_method:delete):

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

查看日志并使用Firebug我可以确认在ajax帖子发生时在请求标头中发送了正确的cookie值,但似乎在某些时候Rails丢失了这个值并因此丢失了会话,因此它重定向到登录页面,永远不会到达方法。

我已经尝试了所有我能想到的调试这个但是我想到这可能是Rails中的一个错误。我正在使用Rails 3.0.4和jQuery 1.5,如果这有帮助的话。我发现常规(即非ajax)获取和发布请求的工作非常奇怪,并且ajax获取请求工作没有问题,这只是ajax帖子没有。

我们将非常感谢您尝试解决此问题的任何帮助!

非常感谢,
戴夫

4 个答案:

答案 0 :(得分:113)

我将回答我自己的问题,因为我已经设法弄清楚发生了什么。我会在这里发布,以防它对其他人有用!

在进一步调查之后,我发现假定用CSRF令牌设置请求标头的代码不是。这是原始代码:

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

发生的事情是此代码未设置标头,Rails正在接收Ajax请求,令牌不匹配并且正在重置会话。这用于引发一个ActionController :: InvalidAuthenticityToken错误(我想如果引发错误我会早点抓住这个......哦,好吧),但是自从Rails 3.0.4以来它现在只是悄悄地重置会话。

所以要在标题中发送令牌,你必须这样做(非常感谢this marvellous blog post):

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

现在一切正常。哪个好。

答案 1 :(得分:5)

我发现了另一个案例:

您是否在应用程序布局文件中设置了'csrf_meta_tag'?

在我的情况下,我没有设置该标记,并且遇到了与您相同的问题。

在app / views / layouts / application.html.erb中设置csrf_meta_tag后,一切正常!

最后,谢谢你帮我找到了根本原因!非常感谢〜

答案 2 :(得分:0)

这就是3.0系列中official jquery-ujs rails adapter的含义。您必须记住在升级rails版本时保持更新。

对我来说,从3.0.3升级到3.0.8.rc4也意味着手动从链接的仓库中提取src/rails.js文件。

由于Rails 3.1最终切换到jQuery,因此在更新rails(并使用3.1的内置资产管道)时,应该通过jquery-rails gem进行自动更新。

答案 3 :(得分:0)

如果将csrf_meta_tag正确发送到服务器后仍然存在问题。确保您的会话存储区配置正确。

如果您的:secure中的session_store.rb设置为true,则cookie(会话)将不会传输到您的http服务器。 docs:https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html