必须使用独立包echo-jwt/v4,内置JWT中间件已于2026年初移除;注册需e.Use(echojwt.WithConfig(jwtConfig)),注意SigningKey为[]byte、ContextKey统一、KeyFunc校验alg和签名方法、时间校验容忍漂移,并为WebSocket单独实现握手鉴权。

直接用 echo-jwt/v4,别碰旧版内置 JWT 中间件——它早在 2026 年初就被移除了。
安装和注册 echo-jwt/v4 中间件
新版必须显式安装独立包,且注册顺序影响后续权限逻辑:
-
go get github.com/labstack/echo-jwt/v4(注意/v4后缀,v3 不兼容) - 注册时用
e.Use(echojwt.WithConfig(jwtConfig)),不是middleware.JWT(...) -
jwtConfig.SigningKey必须是[]byte,传string会 panic - 若需在后续中间件(如 RBAC)中读取用户信息,
jwtConfig.ContextKey要和下游一致,例如设为"user"
KeyFunc 里必须拒绝 alg:none 和校验签名方法
默认 KeyFunc 不检查算法头,攻击者可构造 alg:none token 绕过签名验证:
- 在
jwtConfig.KeyFunc中显式判断:token.Header["alg"] == "none"→ 直接返回 error - 同时确认签名方法类型:
_, ok := token.Method.(*jwt.SigningMethodHMAC),不匹配就拒 - 别只写
return jwtKey, nil—— 这等于放行所有算法
时间校验要容忍服务端时钟漂移
exp、nbf 字段默认校验严格,但生产环境服务端与客户端时间不同步很常见:
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
- 加
jwt.WithValidTimeFunc(func(t time.Time) bool { return t.After(time.Now().Add(-5 * time.Second)) }) - 确保签发时
exp是秒级int64,不是毫秒(Go 的time.Now().Unix()正确,.UnixMilli()错) - 如果 token 解析后
token.Valid为 false 但没报错,大概率是时间戳单位或偏移问题
WebSocket 接口不能套用同一套 JWT 中间件
WebSocket 升级前必须完成鉴权,否则 c.Request() 失效,JWT 中间件根本不起作用:
- 不要写
e.GET("/ws", func(c echo.Context) error { upgrader.Upgrade(...) }) - 改用原生
http.HandlerFunc提取r.Header.Get("Authorization")或r.URL.Query().Get("token") - 手动调
jwt.ParseWithClaims验证,失败就http.Error(w, "Unauthorized", 401) - 成功后再调
upgrader.Upgrade(w, r, nil),此时不能再访问c - 用
e.GET("/ws", echo.WrapHandler(yourHandler))挂载,绕过 Echo 中间件链
最易被忽略的是:JWT 中间件只负责解析和基础校验,黑名单、权限检查、用户状态同步这些都得自己补中间件,而且必须链在 echo-jwt 之后——它不会主动查 Redis,也不会管你用户是否已被禁用。









