权限中间件必须用 ctx.locals 而非 context.withvalue,因其是 fiber 原生上下文机制;requirerole 需查缓存或 db 动态校验角色有效性;jwt 解析失败须返回标准 401 错误而非 panic;中间件注册顺序和 strictrouting 配置至关重要。

权限中间件必须用 ctx.Locals 而不是全局变量或 context.WithValue
很多人照搬 net/http 的写法,在 Fiber 中用 context.WithValue(r.Context(), key, value) 传用户信息,结果发现 handler 里取不到——Fiber 的 fiber.Ctx 并不直接继承 http.Request.Context(),它自己维护了一套上下文机制。
正确做法是用 ctx.Locals("user", user) 存,ctx.Locals("user") 取。这个值只在当前请求生命周期内有效,线程安全,且不会污染底层 fasthttp 的复用 context。
- 别在中间件里写
ctx.Context().WithValue(...),完全无效 -
ctx.Locals是 Fiber 原生支持的键值存储,性能开销极低 - 如果用了 JWT,建议存解析后的
jwt.MapClaims或轻量结构体,别存原始 token 字符串 - 日志或审计时想打用户 ID,直接
fmt.Sprintf("uid=%v", ctx.Locals("user")),但注意判空
RequireRole 中间件不能只比对 role 字符串
硬编码 if role != "admin" 看似简单,但实际线上会出三类问题:角色被禁用、权限动态变更、多角色叠加(比如 "admin,editor")。真正的权限检查必须查数据库或缓存,至少确认该用户当前是否仍拥有该角色。
- 登录时存入 token 的
role字段只是快照,不能当作权威来源 - 中间件里应调用类似
auth.HasRole(ctx.Locals("user_id").(int), "admin")的函数,内部走 Redis 缓存 + DB 回源 - 若项目小,至少加一层有效期检查:
if !isRoleValid(claims["role"].(string), claims["exp"].(float64)) - 返回 403 时别只写
ctx.Status(403).SendString("forbidden"),加上 traceID 方便排查:ctx.Status(403).JSON(fiber.Map{"error": "forbidden", "trace": ctx.Locals("trace_id")})
fiber.New() 下 RequireRole 必须显式注册,不能依赖 fiber.Default()
用 fiber.Default() 启动服务时,自带 Logger 和 Recover 中间件,它们会在权限中间件之前执行;一旦你提前写了响应(比如 401),Logger 就会把完整请求头(含 Authorization)打到日志里——这属于敏感信息泄露,安全扫描直接 fail。
- 上线必须用
fiber.New(&fiber.Config{StrictRouting: true}),禁用默认中间件 -
StrictRouting: true是推荐配置,配合显式路由注册更可控,比如同时写app.Get("/admin", auth.RequireRole("admin"), adminHandler)和app.Get("/admin/", auth.RequireRole("admin"), redirectTrailingSlash) - 中间件顺序很重要:
app.Use(auth.JWT())必须在app.Use(auth.RequireRole(...))之前,否则ctx.Locals("user")还没设好就进权限校验了 - 别在
RequireRole里调ctx.Next()—— 放行才 return,拒绝就直接结束,Fiber 不会继续往下走
JWT 解析失败时不要 panic,要统一返回标准错误格式
Fiber 的中间件签名是 func(c fiber.Ctx) error,但很多人把 JWT 解析失败直接 panic 或 log.Fatal,导致整个服务崩溃。真实场景中 token 过期、签名错误、字段缺失都是高频情况,必须当成业务错误处理。
- 解析失败统一返回
ctx.Status(401).JSON(fiber.Map{"code": "invalid_token", "message": "token expired or malformed"}) - 别用
jwt.Parse的原始 error 返回给前端,里面可能含密钥长度、算法名等敏感细节 - 如果用了
github.com/gofiber/fiber/v3/middleware/keyauth,它的Validator函数返回keyauth.ErrMissingOrMalformedAPIKey才会触发 401,其他 error 默认 500 - 测试时故意发一个过期 token,看是不是返回 401 而不是 500,这是最容易漏掉的验收点
ctx.Locals 的生命周期边界——它不跨中间件自动传递,每个中间件都得自己取、自己判、自己终止。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











