keyauth中间件必须手动注册且位置不能错:需在业务路由前调用app.use(fiber.keyauth(...)),否则请求绕过校验;v3版本须传fiber.keyauthconfig{}结构体,validator和extractor字段不可缺,验证函数耗时应低于5ms。

KeyAuth中间件必须手动注册且位置不能错
KeyAuth不是开箱即用的全局功能,它必须作为中间件显式注册,而且顺序很关键:必须放在业务路由注册之前,否则请求压根不会经过它。常见翻车是把 app.Use(fiber.KeyAuth(...)) 写在 app.Post("/api/user", handler) 之后,结果所有接口都绕过校验。
另外,Fiber v3 的 fiber.KeyAuth() 不再接受函数式参数,必须传 fiber.KeyAuthConfig{} 结构体。漏掉 Validator 字段会导致中间件直接 panic;不设 Extractor 则默认只从 X-Api-Key Header 取值,其他字段名一律失败。
密钥提取路径要和客户端实际发送方式严格对齐
客户端发的是 apikey 头?那必须写 keyauth.FromHeader("apikey") ——大小写敏感,ApiKey 或 APIKEY 都拿不到值。调试时用 GET 带 ?key=xxx?那就得配 keyauth.FromQuery("key")。但注意:FromQuery 模式会让密钥出现在 access log 和代理记录里,生产环境禁用。
多位置 fallback 是可行方案,但要注意组合逻辑:
-
keyauth.FromHeader("X-Api-Key")对所有请求生效 -
keyauth.FromQuery("api_key")仅对 GET/HEAD 生效 -
keyauth.FromForm("api_key")仅对application/x-www-form-urlencoded和multipart/form-data生效,JSON 请求里永远为空
验证函数必须快、纯、无副作用
KeyAuth 的 Validator 函数会在每次请求时同步执行,它不能做数据库查询、HTTP 调用或任何可能超时的操作。实测耗时超过 5ms 就会拖慢整条链路,尤其在高并发下放大延迟。
推荐做法是预加载合法密钥到内存 map 或使用带 TTL 的 sync.Map 缓存,验证时只做 O(1) 查找。返回 false 时不要自己写响应 —— 中间件内部会自动返回 401;你只需要专注判断逻辑:
func myValidator(c fiber.Ctx) bool {
key := c.Get("X-Api-Key") // 或 extractor 提取后的值
if key == "" {
return false
}
// 假设 validKeys 是预热好的 map[string]bool
return validKeys[key]
}
别混淆 KeyAuth 和角色菜单鉴权的适用场景
KeyAuth 解决的是“这个请求有没有资格进系统”的问题,属于网关级粗粒度控制;而角色菜单鉴权(比如判断用户能否调用 /api/user/delete)是业务级细粒度控制,必须在 KeyAuth 放行后、业务 handler 执行前做。
两者不能互相替代:只做 KeyAuth,恶意用户拿到一个有效密钥就能扫全站接口;只做角色鉴权,没密钥的请求也能撞进路由层,浪费资源甚至触发日志/监控误报。典型结构是:
- 全局
app.Use(fiber.KeyAuth(...))→ 拦住非法来源 - 路由级中间件(如
app.Post("/api/user/delete", authByRole("user:delete"), handler))→ 拦住越权操作
KeyAuth 的 ErrorHandler 只能定制 401 响应格式,它不处理 403;权限不足必须由下游中间件自己返回 403,且不能依赖 ctx.Next() 向后传递错误状态 —— 一旦写了响应头,Fiber 就终止流程了。











