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

Rails中devise-jwt登录后未更新User模型jti属性的问题

解决Devise-JWT的JTIMatcher策略登录后不更新jti的问题

我之前也碰到过一模一样的困惑,完全懂你的感受——默认情况下,Devise::JWT::RevocationStrategies::JTIMatcher 策略并不会在用户每次登录时自动更新jti字段,这和你预期的自动更新行为确实有出入。

为什么jti不会自动更新?

JTIMatcher的核心设计逻辑是通过对比token中的jti和数据库里的jti来实现token撤销:当用户执行登出操作时,gem会调用revoke_jwt方法生成新的jti,这样之前的token因为jti不匹配就会直接失效。但登录操作默认不会触发这个逻辑,gem会复用用户已有的jti生成新token,所以你才会看到jti从未更新。

如何实现登录时自动更新jti?

如果你的需求是每次登录都让之前的所有token失效,那么确实需要手动添加登录回调来更新jti,这是符合当前gem设计逻辑的操作。具体可以这么做:

在你的User模型中添加登录后的回调:

class User < ApplicationRecord
  include Devise::JWT::RevocationStrategies::JTIMatcher
  devise :database_authenticatable, :recoverable, :trackable, :validatable,
         :jwt_authenticatable, jwt_revocation_strategy: self

  # 添加登录后更新jti的回调
  after_sign_in :rotate_jti

  def jwt_payload
    super.merge({ custom: 'data' })
  end

  private

  def rotate_jti
    # 用update_column跳过验证直接更新字段,避免不必要的校验
    update_column(:jti, SecureRandom.uuid)
    # 如果需要触发模型回调,也可以用update!:
    # update!(jti: SecureRandom.uuid)
  end
end

额外注意事项

  • 确认你的devise.rb配置中已经正确设置了JWT的分发和撤销路由,比如:
    Devise.setup do |config|
      # 其他配置...
      config.jwt do |jwt|
        jwt.secret = ENV['DEVISE_JWT_SECRET_KEY']
        # 登录请求分发token
        jwt.dispatch_requests = [['POST', %r{^/login$}]]
        # 登出请求触发撤销(此时JTIMatcher会自动更新jti)
        jwt.revocation_requests = [['DELETE', %r{^/logout$}]]
      end
    end
    
  • 如果你不需要每次登录都失效旧token,只是疑惑为什么登出时jti也没更新,那需要检查登出接口是否正确触发了Devise的撤销逻辑(比如是否调用了jwt_revocation_strategy的revoke_jwt方法)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:56:49