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

React+Node.js场景下JWT refresh token的最优存储与访问方案咨询

核心原理说明

HttpOnly Cookie的设计目标就是禁止前端JavaScript读取,是防范XSS攻击窃取敏感凭证的标准安全措施,该问题并非配置错误,而是原有的刷新逻辑依赖前端读取refresh token,不符合HttpOnly的使用规范。

推荐解决方案
  • 调整刷新接口交互逻辑:刷新令牌接口无需前端主动传递refresh token,后端直接读取请求附带的Cookie即可。前端调用刷新接口时只需开启凭证携带配置,浏览器会自动将同域下的HttpOnly Cookie附加到请求中,完全不需要前端读取操作。
    • axios请求配置withCredentials: true
    • fetch请求配置credentials: 'include'
  • 跨域配置适配(前后端不同源时必须配置):
    • Express服务端设置响应头Access-Control-Allow-Credentials: true
    • Access-Control-Allow-Origin不能使用通配符*,必须显式指定前端的完整域名
    • 响应头Access-Control-Allow-Headers需允许Authorization字段,适配Access token的请求头传递逻辑
  • 优化Cookie安全属性:在现有httpOnly: true的基础上,增加Secure: true(生产环境开启,仅允许HTTPS传输)、SameSite: Lax(防范CSRF攻击)配置,也可指定path为刷新接口的路径,缩小refresh token Cookie的暴露范围
  • 优化令牌失效处理逻辑:前端调用业务接口收到401状态码时,自动触发刷新接口请求,拿到新的Access token后重放之前失败的业务请求即可;如果刷新接口也返回401/403状态码,说明refresh token已过期/失效,直接跳转登录页要求用户重新认证即可
  • Access token的存储逻辑无需调整,仅存在React状态变量中安全性更高,页面刷新时先触发一次刷新接口获取新的Access token再加载业务即可。
代码示例

后端Express设置Refresh Token Cookie示例

// 登录接口认证通过后设置Cookie
res.cookie('refresh_token', generatedRefreshToken, {
  httpOnly: true,
  secure: process.env.NODE_ENV === 'production',
  sameSite: 'lax',
  maxAge: 7 * 24 * 60 * 60 * 1000, // 与refresh token有效期保持一致,示例为7天
  path: '/api/auth/refresh' // 可选配置,仅刷新接口可访问该Cookie
})

后端刷新接口逻辑示例

const jwt = require('jsonwebtoken')
app.post('/api/auth/refresh', (req, res) => {
  // 直接从Cookie中提取refresh token,无需前端传递
  const refreshToken = req.cookies.refresh_token
  if (!refreshToken) return res.status(401).json({ msg: '认证失效,请重新登录' })

  try {
    // 校验refresh token合法性
    const payload = jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET)
    // 生成新的access token返回
    const newAccessToken = jwt.sign(
      { userId: payload.userId, username: payload.username },
      process.env.ACCESS_TOKEN_SECRET,
      { expiresIn: '15m' }
    )
    res.json({ accessToken: newAccessToken })
  } catch (err) {
    return res.status(401).json({ msg: '刷新令牌失效,请重新登录' })
  }
})

前端调用刷新接口示例(Axios)

// 封装刷新令牌方法
const refreshToken = async () => {
  const response = await axios.post(
    '/api/auth/refresh',
    {},
    { withCredentials: true } // 关键配置,允许携带Cookie
  )
  // 将新的access token存入状态管理
  setAccessToken(response.data.accessToken)
  return response.data.accessToken
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 04:18:01