应先用c.get("authorization")获取头,再trimprefix去"bearer "前缀并校验非空,最后传给jwt解析;解析后须校验token.valid及exp等字段,并将用户信息存入c.locals而非context.value。

中间件里怎么取 Authorization 头里的 Token
直接用 c.Get("Authorization") 或 c.Request().Header.Get("Authorization") 都可以,但要注意格式。JWT 通常带 Bearer 前缀,比如 Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...。不剥离前缀就去解析,ParseToken 会直接 panic 或返回错误。
推荐写法:
- 先用
c.Get("Authorization")获取完整值 - 检查是否为空或不以
"Bearer "开头(注意末尾空格) - 用
strings.TrimPrefix(token, "Bearer ")安全截取 - 再传给 JWT 解析工具,比如
jwt.Parse或gofiber/jwt/v4
为什么不能在 handler 里校验,必须放中间件
Fiber 的中间件是请求生命周期的第一道关卡,next(c) 之前就能拦截非法请求。如果把 Token 校验逻辑写进某个 app.Get("/user", handler) 里,那所有没被这个 handler 覆盖的路由(比如 /health、/public/*)就完全绕过了验证——等于裸奔。
常见错误包括:
- 只在几个关键接口里手写校验,漏掉文件上传、静态资源代理等路径
- 用
if c.Path() != "/login"做白名单,但没处理/login/和/login的路径归一化差异 - 把校验逻辑塞进业务 service 层,导致测试难、复用差、HTTP 状态码返回混乱
如何跳过登录接口但保留其他所有路由校验
Fiber 不像 Spring Boot 那样有 excludePathPatterns,得靠中间件内部判断路径。别用字符串 == 匹配,要用 strings.HasPrefix(c.Path(), "/login") 或正则,否则 /login-history 也会被误放行。
一个稳妥的写法示例:
func AuthMiddleware() fiber.Handler {
return func(c *fiber.Ctx) error {
path := c.Path()
// 白名单:只放行 /login 和 /register 开头的路径(支持 /login、/login/、/login/token)
if strings.HasPrefix(path, "/login") || strings.HasPrefix(path, "/register") {
return c.Next()
}
authHeader := c.Get("Authorization")
if authHeader == "" {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "missing Authorization header"})
}
tokenStr := strings.TrimPrefix(authHeader, "Bearer ")
if tokenStr == authHeader { // 没匹配上前缀,说明格式不对
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "invalid Authorization format"})
}
// 后续解析 token、查黑名单、存用户信息到 c.Locals...
return c.Next()
}
}
解析 Token 后往哪存用户信息
别往 c.Context().Value() 存,Fiber 推荐用 c.Locals。它线程安全、生命周期和请求一致、读写都快。存的时候用键名(比如 "user_id"、"roles"),后续 handler 直接 c.Locals("user_id").(string) 取。
容易踩的坑:
- 用
c.Context().Set(key, value)—— 这是底层 context,Fiber 不保证它在中间件间透传 - 存整个
*User结构体但没做深拷贝,多个并发请求可能读到脏数据 - 解析失败时没 return,继续执行
c.Next(),导致后端以为认证成功 - 没校验 token 的
exp字段,过期 Token 仍被接受
真正麻烦的不是解析 JWT,而是校验后怎么让下游 handler 安全、稳定、无歧义地拿到用户身份——c.Locals 是 Fiber 场景下最直接有效的选择。











