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

Node.js+React网站是否应将Refresh Token存储到数据库?

安全存储与验证Refresh Token的解决方案

核心结论

必须将Refresh Token的哈希值存储到数据库中——httpOnly Cookie只是客户端的安全存储方式,服务端需要独立留存记录来验证token的合法性、有效期和状态,这是防止伪造、滥用token的关键。

数据库存储方案选择

推荐采用独立的Refresh Token表,而非直接存入用户对象的数组中,原因如下:

方案1:存入用户对象(不推荐)

  • 实现简单,直接在用户表加refresh_tokens数组字段,存储token哈希值和过期时间
  • 缺点:多设备登录时数组会膨胀,清理过期token或查询特定token的效率低,扩展性差

方案2:独立Refresh Token表(推荐)

创建一张refresh_tokens表,核心字段包括:

  • id:主键
  • user_id:关联用户表的外键
  • token_hash:Refresh Token的哈希值(禁止存明文)
  • expires_at:过期时间戳
  • revoked_at:可选,标记token是否被主动注销(NULL表示未注销)
  • created_at:创建时间

这种方案的优势:

  • 结构清晰,便于单独管理token生命周期(批量清理过期token、标记注销)
  • 可通过user_id和token_hash创建索引,查询验证效率更高
  • 支持多设备登录场景,每个设备对应一条独立的token记录

完整安全流程

登录阶段

  1. 验证用户账号密码通过后,生成短有效期的Access Token(如15分钟)和长有效期的Refresh Token(如7天)
  2. 使用bcrypt或argon2对Refresh Token进行哈希处理,将哈希值、用户ID、过期时间存入refresh_tokens表
  3. 将Refresh Token设置为HttpOnly、Secure、SameSite=Strict的Cookie返回给客户端;Access Token返回给前端,由前端存在内存中(如React的state或全局状态管理工具)

刷新Access Token阶段

  1. 当Access Token过期,前端携带自动发送的httpOnly Cookie中的Refresh Token,向服务端发起刷新请求
  2. 服务端取出Refresh Token,对其哈希后查询refresh_tokens表:
    • 若存在对应哈希值、未过期、未被注销,则生成新的Access Token返回给前端
    • 可选实现滚动刷新:生成新的Refresh Token,替换数据库中的旧哈希值和过期时间,同时更新客户端的Cookie(旧Token立即失效)
  3. 若验证失败(token不存在、过期、已注销),返回401状态码,引导用户重新登录

注销阶段

  1. 前端发起注销请求,服务端从Cookie中取出Refresh Token,哈希后在refresh_tokens表中标记为已注销(或直接删除记录)
  2. 清除客户端的Refresh Token Cookie

关键安全注意事项

  • 绝对不要存储明文Refresh Token:数据库泄露后,明文token会被直接滥用,哈希处理是必须的
  • Cookie属性必须严格配置:Secure确保仅HTTPS传输,SameSite=Strict防止CSRF攻击,HttpOnly避免XSS窃取
  • 控制Refresh Token有效期:不要设置过长(建议7天以内),平衡安全性和用户体验
  • 滚动刷新时立即失效旧Token:避免同一用户存在多个有效Refresh Token,降低泄露风险
  • 定期清理冗余数据:通过定时任务删除expires_at早于当前时间或已标记revoked_at的记录

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 01:45:34