应使用 echo-jwt/v4 独立包,删除 dgrijalva/jwt-go 引用,确保与 golang-jwt/jwt/v5 兼容;初始化需传非空 []byte 密钥,显式配置 SigningMethod、KeyFunc 等关键字段,黑名单中间件须置于其后并正确读取 c.Get("user")。

直接用 echo-jwt/v4,别碰旧版内置 JWT 中间件——它已被移除,硬套会 panic。
安装和初始化必须用独立包
官方明确废弃了 core 里的 JWT 支持,go get github.com/labstack/echo-jwt/v4 是唯一推荐路径。v4 默认依赖 github.com/golang-jwt/jwt/v5,不兼容老的 dgrijalva/jwt-go(那个已归档)。如果你还在 import dgrijalva/jwt-go,echo-jwt/v4 启动时会报 panic: interface conversion: interface {} is *jwt.Token, not *jwt.Token。
- 删掉所有
github.com/dgrijalva/jwt-go引用 - 确保
echo-jwt/v4和golang-jwt/jwt/v5版本对齐(v4 要求 v5.0+) - 初始化时传入
[]byte密钥,不是字符串字面量——"secret"可以,但os.Getenv("JWT_KEY")必须非空,否则SigningKey为 nil 会导致token is invalid错误却不提示原因
echojwt.Config 关键字段不能省
只配 SigningKey 是最常见翻车点。v4 的 ParseWithClaims 默认不校验时间、不限算法、不拒绝 alg: none,线上极易被绕过。
-
SigningMethod显式设为"HS256"(即使默认是它,也得写出来) -
ContextKey建议保持默认"user",后续中间件如 RBAC 才能统一取c.Get("user") -
TokenLookup如果前端把 token 放在X-Auth-Tokenheader 里,就得写"header:X-Auth-Token",不能只靠默认的"header:Authorization" - 必须配
KeyFunc来拦截alg: none:函数里检查token.Header["alg"] != "HS256"就 return nil, error
黑名单必须链在 echojwt 后面,不能合并或前置
echo-jwt/v4 本身不做黑名单——它只解析、验签、填 context。你想“登出即失效”,就得在它之后加一个中间件,从 c.Get("user") 拿出已解析的 *jwt.Token,再查 Redis。
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
- 顺序必须是:
e.Use(echojwt.WithConfig(cfg))→e.Use(blacklistMw),反了会拿不到"user" -
blacklistMw里直接token := c.Get("user").(*jwt.Token),别再调jwt.Parse——重复解析浪费 CPU,且可能因配置不一致导致结果不同 - 查 Redis 用
revoked:{jti},key 要带前缀避免冲突;TTL 设为和 tokenexp对齐,比如 token 15 分钟过期,Redis key 也设EX 900 - 写入时用
SET revoked:{jti} "" EX 900 NX,NX防并发重复登出覆盖 TTL
调试时别手写 token,用 docker-http-https-echo 看原始 header 和 payload
很多 401 不是因为密钥错,而是前端没加 Bearer 前缀,或后端 AuthScheme 配成 "bearer"(小写)而标准要求首字母大写 "Bearer"。
- 启动调试容器:
docker run -e JWT_HEADER=Authorization -p 8080:8080 mendhak/http-https-echo - 用 curl 发请求:
curl -H "Authorization: Bearer xxx" http://localhost:8080,看日志里decoded_jwt字段是否完整、exp是否秒级 int64、jti是否存在 - 如果 decoded 结果为空,说明 header 格式不对,或 token 字符串被 URL 编码截断(比如含
+或/)
真正麻烦的从来不是配对密钥,而是时间偏移、算法兜底、header 大小写、Redis 写延迟这四点——它们不会报错,只会让 token 时而有效时而失效,排查起来要翻三遍日志。










