JWT刷新不能只换token字符串,因access_token存于Authorization Header、refresh_token存于HttpOnly Cookie,二者生命周期、传输方式、校验逻辑均不同;Echo需手动实现验证refresh_token→生成新access_token→安全返回链路。

JWT刷新时为什么不能只换token字符串
因为客户端通常把 access_token 存在 Authorization Header 里,而 refresh_token 往往存在 HttpOnly Cookie 或本地安全存储中——两者生命周期、传输方式、校验逻辑都不同。Echo 框架本身不内置 JWT 刷新机制,必须手动实现「验证 refresh_token → 生成新 access_token → 安全返回」这一链路。
如何用 echo-jwt + 自定义中间件实现刷新逻辑
官方 echo-jwt 中间件只负责解析和校验 access_token,不处理 refresh。你需要额外写一个 POST 路由(如 /auth/refresh),并绕过 echo-jwt 的自动校验(否则它会因 access_token 过期直接拦截):
- 用
c.Request().Cookie("refresh_token")或c.FormValue("refresh_token")获取 refresh token - 手动调用你封装的
ValidateRefreshToken()函数(校验签名、exp、jti 黑名单等) - 校验通过后,用同一套密钥和用户信息调用
jwt.NewWithClaims()生成新的access_token - 响应中用
c.SetCookie()更新 refresh token(可选),并以 JSON 返回新access_token
注意:不要在刷新接口里复用 echo-jwt 中间件,否则过期的 access_token 会导致 401 提前返回,根本进不到你的业务逻辑。
refresh_token 该不该轮换?怎么存才安全
必须轮换。每次成功刷新后,旧 refresh_token 应立即加入黑名单(比如 Redis 的 SET key EX 604800),并下发新值。否则攻击者截获一次就能永久续期。
- HttpOnly + Secure + SameSite=Strict 的 Cookie 是首选存放位置(防止 XSS 泄露)
- 避免把 refresh_token 放在 localStorage —— XSS 可直接读取
- 如果前端是跨域 SPA,需确认 Echo 的
CORS配置允许携带凭证:AllowCredentials: true - refresh_token 的有效期建议设为 7–30 天,远长于 access_token(如 15 分钟)
常见错误:401 却没进刷新路由,或新 token 仍被拒绝
典型现象是前端调用 /auth/refresh 返回 401 或空响应。原因往往不是代码逻辑错,而是协议层细节漏了:
- 前端请求没带
Credentials: 'include',导致 Cookie 不发送(尤其跨域时) - 服务端响应没设置
Content-Type: application/json,Echo 默认可能返回 text/plain,前端 parse 失败 - 新生成的
access_token没包含必需 claim(如exp,iss,sub),导致下游echo-jwt校验失败 - 时间偏差:服务端和客户端系统时间差超 skew(默认 5 秒),
exp或nbf校验直接失败
最易被忽略的是:刷新后前端必须主动把新 access_token 写入后续请求的 Authorization Header,Echo 本身不会帮你透传或覆盖——这一步完全在客户端控制。


















