Echo的middleware.JWT是开箱即用的内置JWT认证中间件,默认仅从Authorization头按Bearer方案提取token,只做签名验证而不校验exp等声明,未授权返回401、缺少头返回400。

middleware.JWT 是 Echo 内置的 JWT 认证中间件,开箱即用,但直接传密钥字符串容易踩坑。它默认只从 Authorization 请求头、按 Bearer scheme 提取 token,不校验过期、不解析自定义 claims、也不自动注入用户信息到 context——这些都得靠配置或后续手动处理。
JWT 中间件默认行为和常见 400/401 错误
直接写 e.Use(middleware.JWT([]byte("secret"))) 后,如果请求没带 Authorization 头,会返回 400 Bad Request;如果头存在但签名无效、格式错误或过期,返回 401 Unauthorized。这不是 bug,是默认策略:它只做「token 解析 + 签名验证」两件事,不做业务级判断(比如检查 exp 是否过期,除非你显式启用)。
容易忽略的点:
-
SigningKey类型必须匹配算法:HS256 用[]byte,RS256 必须用*rsa.PrivateKey或*ecdsa.PrivateKey,混用会 panic - 默认不校验
exp字段,哪怕 token 已过期,只要签名对就放行 - 解析出的
jwt.MapClaims存在 context 里,key 是"user",但不会自动转成结构体,需手动c.Get("user").(jwt.MapClaims)
如何正确提取 token:修改 TokenLookup 配置
很多前端把 token 放 query 参数(如 ?token=xxx)或 cookie(如 X-JWT-Token),而默认只看 header:Authorization,导致一直 400。必须用 JWTWithConfig 显式指定位置:
e.Use(middleware.JWTWithConfig(middleware.JWTConfig{
SigningKey: []byte("secret"),
TokenLookup: "query:token", // 或 "cookie:jwt_token"、"header:X-API-Token"
AuthScheme: "Bearer", // 如果不用 Bearer,比如是 "API",这里要改
}))
注意:TokenLookup 值必须严格匹配格式,多空格、大小写错误(如 "Query:token")都会失效。
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
怎么让中间件校验过期时间并返回有意义的错误
默认 JWT 中间件不调用 token.Claims.VerifyExpiresAt,所以过期 token 也能通过。你需要自定义 ContextKey 并在 handler 里手动校验,或者用 Claims 字段注入带验证逻辑的 claims 类型:
- 最简方式:在路由 handler 里取
c.Get("user"),断言为jwt.MapClaims,再调用VerifyExpiresAt(time.Now().Unix(), true) - 更稳妥方式:定义自己的 claims 结构体,嵌入
jwt.StandardClaims,并在JWTConfig.Claims中传入该类型实例 - 避免全局 panic:别在中间件里直接调
token.Claims.(jwt.MapClaims).VerifyExpiresAt(...),因为非MapClaims类型会 panic
为什么 c.Get("user") 取不到数据?
有三个典型原因:
- 中间件没生效:确认
e.Use(...)在e.GET之前调用,且没被Skipper跳过 - token 解析失败:用
docker run -e JWT_HEADER=Authorization -p 8080:8080 mendhak/http-https-echo本地调试,看是否能自动解码并显示 payload - context key 被覆盖:如果你在其他中间件里也用了
c.Set("user", ...),会覆盖 JWT 中间件设的值;检查ContextKey配置是否与其他中间件冲突
真正麻烦的不是配置 JWT,而是后续怎么安全地从 context 拿用户 ID、角色、权限——这些都得自己从 MapClaims 里取字段、类型断言、容错处理,没有银弹。










