中间件中获取JWT需从Authorization头提取并校验Bearer前缀,用jwt.Parse验签后存用户信息到c.Set;验证失败返回401 JSON而非Redirect;鉴权应通过路由分组实现,避免硬编码路径白名单;刷新Token需独立接口与专用中间件。

中间件里怎么获取并验证 JWT Token
Echo 的中间件函数接收 c echo.Context,Token 通常从 Authorization 请求头提取,格式为 Bearer xxx。直接调用 c.Request().Header.Get("Authorization") 拿到后需手动切分,别忘了校验前缀是否为 "Bearer "(注意末尾空格)。
常见错误是忽略大小写或空格导致解析失败,比如传入 "bearer xxx" 或 "Bearerxxx" 就会漏掉 token。建议用 strings.HasPrefix() 判断再 strings.TrimPrefix() 提取。
- Token 解析后应立即用
jwt.Parse()验签,密钥必须和签发时一致,否则返回token is invalid - 验证通过后把用户 ID 或角色存进
c.Set("user_id", uid),后续 handler 可用c.Get("user_id")获取 - 若验证失败,直接调用
c.JSON(401, map[string]string{"error": "unauthorized"})并 return,避免继续执行
为什么不能在中间件里用 c.Redirect() 跳转登录页
HTTP API 场景下,中间件返回 401 是标准做法;如果项目混用前后端同构(比如 SPA),前端应自行处理 401 并跳转。强行在 Echo 中间件里调用 c.Redirect(302, "/login") 会导致响应体被重定向覆盖,API 客户端收不到 JSON 错误信息,且可能破坏 CORS 头或引发预检失败。
真正需要跳转的场景(如管理后台 HTML 页面),应在路由 handler 中判断,而非全局中间件。中间件只负责“鉴权”这件事,不负责“引导用户补救”。
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
- API 接口统一返回
401+ JSON,由前端决定下一步 - HTML 路由可单独加一层 wrapper,例如
authHTMLMiddleware,内部才用Redirect - 别在中间件里写
return后还继续执行逻辑,Echo 不会自动中断链式调用
如何让部分路由跳过身份验证中间件
Echo 不支持中间件“排除”语法,只能靠路由分组实现。把需要鉴权的路由全放进 e.Group("/api"),然后对该 group 应用中间件;登录、注册等公开接口则挂在根 group 或独立 group 上。
别试图在中间件里写一堆 if path == "/login" || path == "/register" 来绕过,这会让中间件职责混乱,也容易漏掉新接口。
- 正确方式:
auth := e.Group("/api"); auth.Use(authMiddleware); auth.GET("/profile", profileHandler) - 错误方式:在中间件里硬编码路径白名单,后续加个
/health就得改中间件 - 如果真有动态跳过需求(比如某些路由按 query 参数决定),应在 handler 内部做二次判断,不在中间件层处理
JWT 过期后刷新 Token 怎么设计
单纯依赖中间件无法完成刷新逻辑——因为刷新需要旧 Token 换新 Token,而中间件只做“检查”,不负责“响应生成”。必须单独暴露一个 /refresh 接口,在其 handler 中解析旧 Token、验证 refresh_token(或检查 jwt.StandardClaims.Audience 是否为 "refresh")、签发新 Access Token。
这个接口本身要加中间件,但逻辑比普通鉴权复杂:它允许过期的 Access Token(只要没超 refresh 窗口),所以不能复用同一套 authMiddleware。
- 推荐做法:写一个
refreshMiddleware,专门检查RefreshTokenHeader 或 Cookie - Access Token 过期时,前端应捕获 401 并主动调用
/refresh,成功后再重试原请求 - 别把 refresh 逻辑塞进鉴权中间件,否则每次请求都尝试刷新,性能差且易出错

















