jwt认证中间件需配置extractor链覆盖header/query/cookie,next函数显式跳过websocket、健康检查等非api请求,并在validatejwt中绑定用户上下文、统一错误类型、支持多密钥轮换。

直接用 keyauth.New() 配合自定义 Validator 函数,就能完成 JWT 认证;但必须手动处理 token 提取、解析、上下文注入和 WebSocket 跳过逻辑,否则会拦截所有请求或导致握手失败。
JWT 认证中间件怎么配才不拦截非 API 请求
关键在 Next 函数里做路由过滤,不能只靠路径前缀。Fiber 的 keyauth 中间件默认对所有匹配路径的请求执行验证,包括 /health、/metrics 或静态资源——哪怕你挂载在 /api 下,子路径没命中也会 fallback 到 401。
- 必须显式跳过非业务请求:
Next: func(c fiber.Ctx) bool { return !c.IsWebSocket() && !strings.HasPrefix(c.Path(), "/api/") } - WebSocket 握手必须跳过,否则
c.IsWebSocket()在 Upgrade 前返回 false,认证失败后连接直接断开 - 健康检查路径(如
/health)建议统一加到Next条件里,避免每次改路径都去翻中间件配置
validateJWT 函数里最容易漏掉的三件事
这个函数是认证成败的核心,但多数人只写了解析逻辑,忽略了上下文绑定、错误类型和密钥轮换支持。
- 解析成功后必须调用
c.Locals("user", token.Claims),否则后续 handler 拿不到用户信息 - 错误返回不能只写
return false, errors.New("xxx"),要统一用keyauth.ErrMissingOrMalformedAPIKey,否则 Fiber 不会返回标准 401 - 硬编码密钥
[]byte("your-secret-key")不安全,应从config.JWT.Secret读取,并支持多密钥验签(比如旧 token 还在有效期时更换了密钥)
Token 从哪来?Extractor 链必须覆盖常见场景
前端传 token 的方式不止 Authorization Header,query 和 cookie 同样常见,尤其在 SSR 或 iframe 场景下。单靠 FromAuthHeader("Bearer") 会漏掉大量合法请求。
- 优先组合使用:
extractors.Chain(extractors.FromAuthHeader("Bearer"), extractors.FromQuery("token"), extractors.FromCookie("auth_token")) - 注意
FromCookie默认读auth_token,如果前端存的是access_token,得显式传参:extractors.FromCookie("access_token") - 不要用
FromForm("token")处理 POST 表单,WebSocket 握手是 GET 请求,表单字段根本不存在
为什么 WebSocket 连接总是 401?
不是 JWT 本身问题,而是中间件执行时机和请求特征判断出错。WebSocket 升级请求的 Content-Type 是 text/plain,Accept 是 */*,且没有 Authorization header——但很多前端 SDK 会把 token 放 query 里(如 wss://host/ws?token=xxx)。
-
Next函数里必须用c.IsWebSocket(),不能用c.Method() == "GET" && c.Get("Upgrade") == "websocket",因为IsWebSocket()内部已做完整校验 -
Extractor链必须包含FromQuery("token"),否则 query 里的 token 根本不会被提取 - 如果用了反向代理(如 Nginx),确认它没 strip 掉 query 参数——这是生产环境最常被忽略的一环
JWT 认证本身不复杂,但 Fiber 的 keyauth 中间件要求你对请求生命周期有明确控制意识:什么时候该跳过、token 从哪来、解析失败怎么退、用户数据往哪塞。少一个环节,整个链路就断在 401 或 panic 上。











