fiber.middlewarefunc 是 api key 认证的正确入口,因其能统一鉴权、安全比对、透传身份且规避配置陷阱。

为什么 fiber.MiddlewareFunc 是 API Key 认证的正确入口
因为 Fiber 的中间件机制天然适合在请求进入路由前做统一鉴权,fiber.MiddlewareFunc 能直接访问 c.Context,拿到 Authorization 或自定义 Header(如 X-API-Key),且不会干扰后续 handler 的执行流程。用 c.Next() 控制放行,用 c.Status(401).SendString() 拒绝,逻辑干净。
常见错误是把校验逻辑写进每个 handler 里,导致重复、漏判、无法统一响应格式;另一个坑是误用 fiber.Handler 类型——它不接受 fiber.Ctx 作为参数,编译直接报错。
- 必须用
fiber.MiddlewareFunc类型定义中间件函数 - 推荐从
X-API-KeyHeader 读取(比Authorization: ApiKey xxx更轻量,也避开了 Bearer 解析逻辑) - 校验失败时务必调用
c.Abort(),否则即使返回 401,后续 handler 仍会执行
如何安全比对 API Key:别用 ==,改用 subtle.ConstantTimeCompare
直接用 == 比字符串会触发时间侧信道攻击——攻击者通过响应延迟差异可逐步推断出合法 key 的字符。Go 标准库的 crypto/subtle 提供了恒定时间比较函数,必须用它。
注意:subtle.ConstantTimeCompare 要求两个参数都是 []byte,且长度相等。所以得先检查长度是否一致(避免 panic),再转成字节切片比对。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
func apiKeyMiddleware(validKey string) fiber.Handler {
return func(c *fiber.Ctx) error {
key := c.Get("X-API-Key")
if len(key) != len(validKey) {
c.Status(401).SendString("Unauthorized")
return c.Abort()
}
if subtle.ConstantTimeCompare([]byte(key), []byte(validKey)) != 1 {
c.Status(401).SendString("Unauthorized")
return c.Abort()
}
return c.Next()
}
}
怎么把 API Key 存到 c.Locals 供下游 handler 使用
认证通过后,往往需要把 key 对应的用户 ID、权限等级等信息透传下去。c.Locals 是 Fiber 提供的请求上下文本地存储,只在当前请求生命周期内有效,线程安全,比全局 map 或闭包变量更可靠。
别把原始 key 存进去——下游 handler 应该只看到解析后的身份信息;也别存指针或未拷贝的结构体,防止并发修改。
- 认证成功后调用
c.Locals("user_id", userID)和c.Locals("role", "admin") - 下游 handler 用
userID := c.Locals("user_id").(string)取值(注意类型断言) - 如果 key 可能对应多个租户,建议存
c.Locals("tenant_id", tenantID),方便做数据隔离
生产环境必须避开的三个配置陷阱
本地跑通不等于线上可用。Fiber 默认不开启严格模式,有些行为在反向代理后会出问题。
-
X-API-KeyHeader 在 Nginx 或 Cloudflare 后可能被默认过滤,需显式配置underscores_in_headers on;(Nginx)或开启「允许自定义 Header」(CDN) - Fiber 的
StrictRouting设为false时,/api/v1/users/和/api/v1/users会被视为不同路径,但 API Key 中间件挂载在/api/v1前缀下时,容易漏掉带尾斜杠的请求 - 别把 validKey 写死在代码里——用
os.Getenv("API_KEY")或从 viper 配置中心加载,否则每次更新 key 都要重新编译部署
最易被忽略的是日志:不要在 error 日志里打印完整 API Key,哪怕只是调试。至少做掩码处理,比如 "key_***" + key[len(key)-4:]。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










