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

如何在无Devise的Rails API中实现带Refresh Token的JWT认证?

Rails API中实现JWT Refresh Token的方案探讨

背景

我正在现有Rails API应用里实现Refresh Token路由,用的是jwt gem做令牌编解码,不想用Devise,已经自定义了登录、登出路由,核心操作就是JWT.encode和JWT.decode。

我对JWT的理解(如有错误请指正)

通过JWT.encode生成的令牌会发给前端(ReactJS),由客户端存储,每次请求以Bearer Token的形式发送。令牌的过期时间可以作为参数放进JWT.encode的payload里,示例代码如下:

def encode(payload, key, algorithm = 'HS256', header_fields = {})
  Encode.new(payload: payload,
             key: key,
             algorithm: algorithm,
             headers: header_fields).segments
end

JWT整体由三部分组成:

  • Header:包含令牌的相关信息,比如签名算法
  • Payload:存储令牌携带的数据(一般是用户uuid和角色)
  • Signature:通过HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret_key)生成

这意味着编码后的header和payload字符串会和secret_key结合生成HASH,只有令牌数据没被篡改且密钥正确时,哈希值才会一致。如果payload被篡改或者没有正确密钥,签名就会失效,验证失败。当然,要是令牌被盗,别人就能冒充用户,这个问题没法避免。

我的疑问与思路

如果上面的理解是对的,想请教怎么实现Refresh Token路由?流程是:当API请求验证失败(返回403状态码),前端的回调函数会调用Refresh Token路由获取新令牌,再重新发起之前失败的请求。

问题1:后端逻辑如何组织?

Refresh Token需要在生成Access Token后一起返回给前端,所以得在数据库里存储相关数据,用来验证Refresh Token的过期时间、关联的Access Token等。

我之前用Laravel,它的Passport包有个refresh_tokens表,字段包括:

  1. id
  2. access_token_id:但jwt gem不存储数据,也没有Access Token表,这里是不是应该存Access Token本身?
  3. revoked(布尔型):标记令牌是否作废
  4. expiry_at:Refresh Token的过期时间,到期后用户得重新登录
  5. refresh_token:我觉得要加这个字段来关联Access Token(Laravel Passport里没有这个字段)
  6. timestamps

请问在当前Rails的数据库里创建这个结构合理且安全吗?

问题2:Refresh Token怎么生成?

它的有效期要比Access Token长,但不能拥有和Access Token一样的权限。

我自己想了个思路:用JWT.encode生成,payload里加额外的标识数据:

access_token = JWT.encode({user_uuid: user.uuid, role: user.role, type: 'access', exp: 1.hour.to_i})
refresh_token = JWT.encode({user_uuid: user.uuid, role: user.role, type: 'refresh', exp: 3.days.to_i})
# 然后在API中间件验证时,还要检查用户发送的是access还是refresh token

请问这个思路可行吗?有没有其他建议?


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 03:12:44