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

Devise-JWT二次登录后无法找到活跃会话问题求助

问题分析与解决方案

你的问题核心是注销后重新生成的JWT Token无法验证,且注销时无法识别活跃会话,本质是Devise-JWT的token失效逻辑和会话处理未正确配置,加上自定义注销方法依赖current_user导致判断错误。

关键问题点

  1. 注销方法依赖current_user判断会话状态,但注销动作触发时,Devise-JWT已尝试失效token,此时current_user可能无法正确获取,导致误判。
  2. 未正确配置Devise-JWT的token失效策略,旧token未被彻底失效,与新token的验证逻辑冲突。
  3. CSRF配置与API场景不匹配,引发验证冲突。

具体修复步骤

1. 完善User模型的JWT配置

确保User模型启用JWT认证,并指定通过更新jti字段使旧token失效的策略:

# app/models/user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :jwt_authenticatable, jwt_revocation_strategy: Devise::JWT::RevocationStrategies::JTIMatcher
end

2. 修正Devise-JWT初始化配置

在config/initializers/devise.rb中配置JWT的分发、失效规则,确保注销请求触发token失效:

Devise.setup do |config|
  # 保留你的其他Devise配置...

  config.jwt do |jwt|
    jwt.secret = Rails.application.credentials.devise_jwt_secret_key # 确保密钥已正确配置
    jwt.dispatch_requests = [ # 指定返回JWT的请求
      ['POST', %r{^/users/sign_in$}],
      ['POST', %r{^/users/sign_up$}]
    ]
    jwt.revocation_requests = [ # 指定触发token失效的请求
      ['DELETE', %r{^/users/sign_out$}]
    ]
    jwt.expiration_time = 1.day.to_i # 设置token过期时间
    jwt.revocation_strategy = Devise::JWT::RevocationStrategies::JTIMatcher # 关联模型的失效策略
  end
end

3. 重写注销方法,移除current_user依赖

原注销方法依赖current_user判断会话状态,但注销时token已失效,current_user无法正确获取。修改为直接处理token验证逻辑:

class Users::SessionsController < Devise::SessionsController
  respond_to :json

  private

  def respond_with(resource, _opts = {})
    render json: {
      status: { code: 200, message: 'Logged in successfully.' },
      data: UserSerializer.new(resource).serializable_hash[:data][:attributes]
    }, status: :ok
  end

  def respond_to_on_destroy
    # Devise-JWT会自动处理token失效,直接返回成功
    render json: {
      status: 200,
      message: 'Logged out successfully'
    }, status: :ok
  rescue JWT::DecodeError, JWT::VerificationError
    # 捕获无效token的情况,返回未授权
    render json: {
      status: 401,
      message: "Couldn't find an active session."
    }, status: :unauthorized
  end
end

4. 配置API场景的CSRF保护

在ApplicationController中设置适合API的CSRF策略,避免验证冲突:

class ApplicationController < ActionController::API
  protect_from_forgery with: :null_session, if: -> { request.format.json? }
end

验证逻辑说明

  • 每次登录时,Devise-JWT自动生成新的jti值并更新到用户记录,旧token因jti不匹配失效。
  • 注销请求触发时,Devise-JWT再次更新用户jti值,确保当前token立即失效。
  • 移除current_user依赖后,注销方法直接处理token验证结果,避免会话状态误判。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 11:21:07