Rails 没有在 ajax 帖子上重新加载会话
Posted
技术标签:
【中文标题】Rails 没有在 ajax 帖子上重新加载会话【英文标题】:Rails not reloading session on ajax post 【发布时间】:2011-07-04 20:18:05 【问题描述】:我在使用 jQuery 的 Rails 和 ajax 方面遇到了一个非常奇怪的问题(尽管我认为这不是 jQuery 特有的)。
我的 Rails 应用程序使用 cookie 会话存储,并且我有一个非常简单的登录,可以在会话中设置用户 ID。如果会话中未设置 user_id,它会重定向到登录页面。这没有问题。 JQuery GET 请求也可以正常工作。问题是当我执行 jQuery POST 时 - 浏览器发送会话 cookie 正常(我通过 Firebug 确认了这一点并将 request.cookies 转储到日志)但会话为空白,即会话为 。
我在我的 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)get 和 post 请求可以正常工作,而 ajax get 请求可以正常工作,只是 ajax 帖子没有。
我们将不胜感激任何尝试解决此问题的帮助!
非常感谢, 戴夫
【问题讨论】:
【参考方案1】:我将回答我自己的问题,因为我已经设法弄清楚发生了什么。我会把它贴在这里,以防它对其他人有用!
在进一步调查后,我发现应该使用 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'));
);
现在一切正常。哪个不错。
【讨论】:
【参考方案2】:我发现了另一个案例:
您是否在应用程序布局文件中设置了“csrf_meta_tag”?
在我的情况下,我没有设置该标签,并且遇到了同样的问题。
在 app/views/layouts/application.html.erb 中设置 csrf_meta_tag 后,一切正常!
最后,谢谢你帮我找到了根本原因!非常感谢~
【讨论】:
【参考方案3】:这就是 official jquery-ujs rails adapter 在 3.0 系列中的用途。不过,您必须记住在升级 rails 版本时保持更新。
对我来说,从 3.0.3 升级到 3.0.8.rc4 还意味着从链接的 repo 手动获取 src/rails.js
文件。
由于 Rails 3.1 最终切换到 jQuery,未来在更新 rails(并使用 3.1 的内置资产管道)时应该通过 jquery-rails gem 自动更新
【讨论】:
【参考方案4】:如果您在将csrf_meta_tag
正确发送到服务器后仍然有问题。确保您的会话存储配置正确。
如果:secure
在您的session_store.rb
中设置为true,则cookie(会话)将不会传输到您的http 服务器。文档:https://api.rubyonrails.org/classes/ActionDispatch/Cookies.html
【讨论】:
以上是关于Rails 没有在 ajax 帖子上重新加载会话的主要内容,如果未能解决你的问题,请参考以下文章
Rails 仅在生产时才在页面重新加载时丢失会话变量 current_user_id(React 16.13、Rails 6、Heroku)