You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 5.2登录成功后Warden获取用户为nil无法加载首页

问题背景
  • 部署环境:ubuntu 18.04
  • 异常版本栈:rails 5.2.8、ruby 2.5.1、devise 4.5.0(所有版本号高于4.5的devise均会触发该问题)、warden 1.2.9
  • 历史正常版本栈:rails 5.0.1、ruby 2.3.3、devise 4.2.0、warden 1.2.7
  • 故障现象:用户登录流程执行成功(数据库可查询到登录记录),登录完成重定向到首页时current_user变为nil/失效,接口返回401未授权,最终跳转回登录页。
日志信息

异常场景日志

[2022-06-02 13:02:21] INFO -- SIGN-IN SIGN-IN SIGN-IN SIGN-IN SIGN-IN SIGN-IN SIGN-IN SIGN-IN SIGN-IN SIGN-IN SIGN-IN SIGN-IN SIGN-IN
[2022-06-02 13:02:21] DEBUG -- Warden::Manager.after_authentication: User USER@live.com has signed in.
[2022-06-02 13:02:21] INFO -- ^^^^^^^^^ check_reference: request.env['HTTP_REFERER'] = https://SERVER.com/d/users/sign_in  params[:controller] = users/sessions
[2022-06-02 13:02:21] INFO -- ======================= SessionsController: format.html  current_user: #<User signed_in: true, id: 25, email: "USER@live.com", first_name: "FIRST", last_name: "LAST", role: "Administrator", auto_signout_enabled: true, password_changed: false, force_password_reset: false, updated_at: "2022-06-02 20:02:21", created_at: "2020-01-10 13:24:20">
[2022-06-02 13:02:21] INFO -- ======================== application_controller: after_sign_in_path_for
[2022-06-02 13:02:21] INFO -- Redirected to http://LOCALAPP/
[2022-06-02 13:02:21] INFO -- ======================= SessionsController: User USER@live.com signed-in from Web browser.
[2022-06-02 13:02:21] INFO -- Completed 302 Found in 93ms (ActiveRecord: 4.0ms)
[2022-06-02 13:02:21] INFO -- Started GET "/" for 127.0.0.1 at 2022-06-02 13:02:21 -0700
[2022-06-02 13:02:21] INFO -- Processing by RuntimeController#index as HTML
[2022-06-02 13:02:21] DEBUG -- Warden::Manager.after_failed_fetch: User nil   opts: {:scope=>:user}
[2022-06-02 13:02:21] INFO -- Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms)
[2022-06-02 13:02:21] INFO -- Warden::Manager.after_failed_fetch: User is nil? true   opts: {:scope=>:user}   auth: Warden::Proxy:20581780 @config={:default_scope=>:user, :scope_defaults=>{}, :default_strategies=>{:user=>[:database_authenticatable]}, :intercept_401=>false, :failure_app=>#<Devise::Delegator:0x0000000004d66b28>}

正常场景日志

[2022-06-02 16:14:36] INFO -- ********************************* RUNTIME VIEW *********************************
[2022-06-02 16:14:36] DEBUG -- [VIEWS HELPER] get_view_connectivity view_id: 15
<<continue to load home page >>

异常捕获代码

通过如下Warden回调可捕获用户为nil的状态:

Warden::Manager.after_failed_fetch do |user, auth, opts|
  Rails.logger.debug("Warden::Manager.after_failed_fetch: User is nil? #{user.nil?}   opts: #{opts.inspect}   auth: #{auth.inspect}".default_warn)
end
已尝试方案
  • 在rails 5.2.8环境中降级安装warden 1.2.7,问题未解决
  • 尝试降级到devise 4.2.0,但该版本依赖railties (< 5.1, >= 4.1.0),无法在rails 5.2环境中运行
  • 过往遇到相同问题只能回退全量旧版本,但旧版本Ruby Gem维护成本极高,新增、升级Gem时频繁出现版本兼容问题,调试耗时极长
可行修复方案(无需回退版本)

1. 修正session cookie配置

Rails 5.2默认新增了cookie安全校验规则,配置错误会导致重定向时session丢失,修改config/initializers/session_store.rb:

Rails.application.config.session_store :cookie_store, 
  key: '_your_app_session', # 替换为自身应用的session key
  domain: :all, # 多子域部署必填,单域部署可直接写对应域名,禁止留空
  tld_length: 2, # 域名层级为3级(如a.b.com)设为2,多级域名(如a.b.c.com)对应调整数值
  same_site: :lax, # 禁止设为:strict,否则跨重定向场景浏览器会拦截cookie
  secure: Rails.env.production? # HTTPS环境设为true,纯HTTP环境必须设为false

2. 重写Warden序列化逻辑兼容Devise 4.5+规则

Devise 4.5之后修改了用户对象序列化到session的默认逻辑,如果User模型存在不可序列化的自定义属性,会导致反序列化失败返回nil,在config/initializers/devise.rb中添加如下配置,强制使用用户ID做序列化:

config.warden do |manager|
  manager.serialize_into_session(&:id)
  manager.serialize_from_session { |id| User.find_by(id: id) }
end

3. 兼容Rails 5.2 cookie签名算法升级

Rails 5.2默认使用SHA256作为cookie签名算法,从旧版本升级时会存在旧cookie无法解析的问题,在config/application.rb中添加兼容配置:

config.action_dispatch.use_authenticated_cookie_encryption = true
config.action_dispatch.signed_cookie_digest = "SHA256"
# 升级过渡期添加,兼容旧版本生成的SHA1签名cookie,等所有旧cookie自然过期后可删除
config.action_dispatch.cookies_rotations.tap do |cookies|
  cookies.rotate :signed, Rails.application.credentials.secret_key_base, digest: "SHA1"
end

4. 排查CSRF校验重置session问题

如果CSRF token校验失败,Rails会自动重置session导致登录态丢失,在app/controllers/application_controller.rb中添加异常捕获排查:

rescue_from ActionController::InvalidAuthenticityToken do |e|
  Rails.logger.error "CSRF校验失败,session已重置: #{e.message}, referer: #{request.referer}"
  redirect_to new_user_session_path
end

内容的提问来源于stack exchange,提问作者djm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 06:57:28