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

Refresh Token授权流程是什么?Express项目JWT鉴权实操咨询

Express 项目 JWT 双Token(Access + Refresh)授权全流程

双Token机制的核心逻辑是拆分令牌职责:短期的Access Token负责接口访问鉴权,泄露后风险窗口极短;长期的Refresh Token仅负责续签新的Access Token,支持服务端吊销,兼顾使用体验和安全。以下是可直接落地的完整执行步骤:

1. 登录环节:双Token生成与存储

  • 前端提交账号密码后,后端首先查询数据库匹配用户记录,用bcrypt比对提交密码和库中存储的密码哈希,校验不通过直接返回401状态码。
  • 账号密码校验通过后,分别生成两个独立签名的JWT:
    • Access Token:有效期设为15~30分钟,payload仅存放必要的非敏感字段(用户ID、角色权限),使用独立的ACCESS_TOKEN_SECRET密钥签名:
      const accessToken = jwt.sign(
        { userId: user._id, role: user.role },
        process.env.ACCESS_TOKEN_SECRET,
        { expiresIn: '15m' }
      );
      
    • Refresh Token:有效期设为7~30天,payload仅保留用户ID即可,使用和Access Token完全独立的REFRESH_TOKEN_SECRET密钥签名:
      const refreshToken = jwt.sign(
        { userId: user._id },
        process.env.REFRESH_TOKEN_SECRET,
        { expiresIn: '7d' }
      );
      
  • 绝对不要把Refresh Token明文存入数据库:和密码存储逻辑一致,将生成的Refresh Token用bcrypt计算哈希后,关联用户ID、过期时间、设备标识(可选,用于多设备管理)存入用户表的refreshTokens数组字段,避免数据库拖库导致所有令牌泄露。
  • 令牌返回规则:Access Token直接放在响应体返回给前端,前端存在运行时内存中(比如Vue/React的全局状态,不要存localStorage降低XSS被盗风险);Refresh Token通过httpOnly、secure、sameSite: 'Strict'属性的Cookie下发,前端JS无法读取,自动随同域请求携带,大幅降低泄露概率。

2. 普通受保护接口鉴权逻辑

  • 前端每次调用受保护接口,将Access Token放在请求头Authorization: Bearer <accessToken>字段中携带。
  • 后端编写统一鉴权中间件,校验请求携带的Access Token:
    const authRequired = (req, res, next) => {
      const authHeader = req.headers.authorization;
      if (!authHeader?.startsWith('Bearer ')) return res.sendStatus(401);
      const accessToken = authHeader.split(' ')[1];
      jwt.verify(accessToken, process.env.ACCESS_TOKEN_SECRET, (err, payload) => {
        if (err) return res.sendStatus(403); // Token无效、过期直接返回权限错误
        req.user = { userId: payload.userId, role: payload.role };
        next();
      });
    };
    
  • 校验通过后将用户信息挂载到req对象上放行接口,校验失败直接返回403状态码。

3. Access Token过期后的静默续签流程

这是双Token配合的核心环节,全程用户无感知:

  • 前端封装统一的请求响应拦截器,只要收到接口返回的403状态码,不直接跳转登录页,先静默调用/api/auth/refresh续签接口。注意这个接口不要加上面的Access Token鉴权中间件。
  • 后端续签接口执行以下校验逻辑:
    1. 从请求Cookie中读取Refresh Token原文,先用REFRESH_TOKEN_SECRET校验签名合法性,签名不合法直接返回401要求重新登录。
    2. 签名校验通过后,从payload中取出用户ID,查询数据库中该用户关联的所有Refresh Token哈希记录。
    3. 用bcrypt将请求携带的Refresh Token原文和库中存储的哈希逐一比对,找不到匹配记录、或匹配记录已过有效期,直接返回401(这种情况大概率是令牌被盗用,可额外加异常日志告警)。
    4. 所有校验通过后,生成新的15分钟有效期Access Token返回给前端。
    5. 可选安全增强:每次续签时同步生成新的Refresh Token,删除库中旧的Refresh Token哈希记录,新Token重新通过httpOnly Cookie下发,实现滚动续期,进一步压缩令牌泄露后的可用窗口。
  • 前端拿到新的Access Token后,更新内存中存储的令牌值,自动重发之前失败的请求,用户完全感知不到续签过程。
  • 如果续签接口返回401,说明Refresh Token已过期或无效,此时再清除本地登录状态,跳转至登录页要求用户重新登录。

4. 特殊场景处理

  • 用户主动登出:后端接收到登出请求后,从Cookie中读取Refresh Token,校验通过后将对应的哈希记录从用户的refreshTokens数组中删除,同时清除前端的Refresh Cookie,令牌即刻失效。
  • 强制下线/修改密码:直接清空该用户在数据库中存储的所有Refresh Token哈希记录,所有设备的登录状态会在下次Access Token过期后触发续签时失效,要求重新登录。
  • 基础安全红线:
    • 两个JWT签名密钥必须用足够长度的随机字符串,存放在环境变量中,绝对不要硬编码提交到代码仓库
    • 绝对不要在JWT payload中存放密码、手机号等敏感信息:JWT payload仅做base64编码,没有加密,任何人拿到令牌都可以直接解码读取内容
    • 生产环境必须启用HTTPS,Refresh Token对应的Cookie必须开启secure属性,防止传输过程被截获

内容的提问来源于stack exchange,提问作者Ben Böckmann

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 12:45:32