我正在使用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帖子没有。
我们将非常感谢您尝试解决此问题的任何帮助!
非常感谢,
戴夫
答案 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