Echo框架不处理JWT过期逻辑,过期检查完全依赖jwt.ParseWithClaims的选项配置;必须显式添加jwt.WithExpirationRequired()等选项才能拦截过期token,否则仅签名正确即放行。

直接说结论:Echo 框架本身不处理 JWT 过期逻辑,echo-jwt/v4 只做基础解析和签名验证;过期检查是否生效、容忍多少时钟偏差、是否允许 exp 字段缺失——全靠你配的 jwt.ParseWithClaims 参数和 KeyFunc 里的行为决定。
为什么 echo-jwt 默认“过期了也不报错”?
因为 echo-jwt 底层调用的是 golang-jwt/jwt/v5 的 ParseWithClaims,而这个函数默认不强制校验 exp 字段。如果你没显式传入 jwt.WithExpirationRequired() 或 jwt.WithValidTimeFunc,它就会安静地放过已过期的 token。
- 现象:请求带一个过期 2 小时的 token,
echo-jwt中间件仍放行,后续业务代码才发现用户身份异常 - 根本原因:
token.Valid返回true,仅因签名正确 + 时间字段存在(哪怕exp < now) - 正确做法:在
echo-jwt.Config的SigningMethod和KeyFunc外,必须加Options数组
如何让过期 token 真正被拦截?
不是靠中间件开关,而是靠 jwt.ParseWithClaims 的选项组合。下面这段配置才是生产环境该写的:
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
config := jwt.Config{
KeyFunc: func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return jwtKey, nil
},
Options: []jwt.ParserOption{
jwt.WithExpirationRequired(), // 强制 exp 存在且未过期
jwt.WithIssuedAt(), // 强制校验 iat
jwt.WithValidTimeFunc(func(t time.Time) bool {
// 容忍服务端与客户端最多 ±5 秒时钟漂移
return t.After(time.Now().Add(-5 * time.Second)) &&
t.Before(time.Now().Add(5 * time.Second))
}),
},
}
e.Use(jwt.WithConfig(config))
- 缺
WithExpirationRequired()→ 过期 token 不报错 - 缺
WithValidTimeFunc→ 服务器时间比客户端快 3 秒,刚签发就报token is expired -
WithIssuedAt()能防重放,但必须配合iat字段签发,否则解析失败
过期后怎么让用户无感续期?
别指望 echo-jwt 帮你刷新 token——它连 refresh_token 都不认识。你要自己暴露一个 /auth/refresh 接口,规则必须严格:
- 该接口不能走
echo-jwt中间件(否则过期 token 进不来),改用自定义 header 解析或 cookie 提取 - 从请求中拿到旧
refresh_token,查 DB/Redis 验证有效性、绑定关系、未被吊销 - 验证通过后,签发一对新 token:
access_token(15 分钟)+refresh_token(7 天),并更新存储中的旧 refresh token 状态 - 务必在响应头里设
HttpOnly+SecureCookie 存 refresh token,别放 body 里
黑名单校验必须放在 echo-jwt 之后
很多人想在 echo-jwt 里塞黑名单逻辑,这是错的。它设计就是无状态的,强行改源码会破坏升级路径。
- 正确链路:
echo-jwt→blacklistMiddleware→ 业务 handler - 黑名单中间件只做一件事:从
c.Get("user")断言出*jwt.Token,取token.Claims.(jwt.MapClaims)["jti"],查 Redis keyrevoked:{jti} - 注意 fallback:如果没设
jti,可用token.Raw做哈希后查,但性能差、易冲突 - Redis 写入要用
SET revoked:{jti} "" EX 900 NX,避免并发登出时漏写
最常被忽略的一点:echo-jwt 放行的 token,不代表它“有效”,只代表“格式合法、签名正确、时间字段没明显错”。真正的业务有效性(是否登出、是否被吊销、是否超出设备限制)必须由你自己的中间件补全,而且顺序不能错——它永远在 echo-jwt 之后,且不能重复解析 token。

















