在fiber中注册jwt中间件需用github.com/gofiber/jwt/v3,通过jwt.new()配置signingkey,支持全局app.use()或分组api.use()注册;校验失败默认返回401及标准json,可自定义errorhandler;payload存于c.locals["user"],需类型断言提取;/login路由必须绕过该中间件。

JWT中间件怎么注册并拦截未登录请求
直接在路由组上用 Use 注册 JWT 验证中间件,是最常用也最稳妥的方式。它会在每次请求进入该组前检查 Authorization 请求头中的 Bearer Token 是否合法、未过期、签名正确。
常见错误是把中间件注册在 app.Get 等单个路由上,导致其他同组路由(比如 /api/users 和 /api/posts)漏掉校验;或者注册顺序错位,比如把 Use 放在 Handle 之后,中间件根本不会执行。
- 必须用
app.Party("/api").Use(jwtMiddleware)统一加在分组上,而不是每个 handler 单独挂 -
jwtMiddleware函数内部要用ctx.StatusCode(401)+ctx.Stop()显式中断流程,不能只return - Token 解析失败时,
services.UserTokenService.GetCurrent(ctx)返回nil,这时要立刻终止后续 handler 执行
如何从 Context 提取用户信息并透传到业务层
Iris 的 Context 支持自定义键值存储,这是传递认证后用户数据的核心机制。不要在中间件里直接调用数据库查用户,而应在验证通过后把用户 ID 或结构体塞进 ctx.Values().Set("user", user),下游 handler 再用 ctx.Values().Get("user") 拿。
容易踩的坑是类型断言不安全:如果没做空值判断就直接 user := ctx.Values().Get("user").(*model.User),一旦中间件没执行或出错,运行时 panic。更稳妥的做法是加一层校验:
if u, ok := ctx.Values().Get("user").(*model.User); ok && u != nil {
// 安全使用 u
} else {
ctx.StatusCode(403)
ctx.WriteString("forbidden")
ctx.Stop()
return
}
RBAC 权限校验该放在哪一层
权限控制不能只靠中间件“一刀切”,得拆成两层:JWT 中间件负责身份认证(你是谁),RBAC 校验逻辑应作为独立中间件或业务内联判断,放在认证之后、具体 handler 之前。
例如管理后台接口 /admin/users,需要同时满足「已登录」+「角色有 admin:users:read 权限」。这时可以写一个 rbacMiddleware("admin:users:read"),并在路由组中链式注册:adminGroup.Use(jwtMiddleware).Use(rbacMiddleware("admin:users:read"))。
- 权限标识建议统一用冒号分隔的字符串(如
"system:config:write"),便于 Casbin 规则匹配 - 不要在每个 handler 里重复查权限,中间件里查一次、存到
ctx.Values()即可 - Casbin 的
Enforce调用本身有开销,建议对高频接口做内存缓存(如用sync.Map缓存userID+permission结果)
为什么 auth 中间件有时不生效或报 404
这不是中间件写错了,大概率是路由注册顺序或 Party 分组嵌套问题。Iris 的中间件只对注册时已声明的子路由生效,动态添加的路由(比如用 app.Any 或后期 HandleFunc 补的)不会自动继承。
典型现象:你在 apiGroup := app.Party("/api") 上注册了 Use(authMw),但某个接口是 app.Get("/api/v2/xxx", handler) ——注意这里没走 apiGroup,所以中间件完全不触发。
- 所有受保护路由必须通过
apiGroup.Get、apiGroup.Post等方式注册 - 避免混用
app.Get和Party().Get,否则中间件作用域混乱 - 调试时可在中间件开头加
fmt.Printf("auth middleware hit: %s\n", ctx.Path())确认是否被调用
ctx.Stop() 导致后续中间件跳过(比如日志中间件收不到请求),也不能忘记 ctx.Stop() 让非法请求继续往下走。这个边界点,得靠 ctx.StatusCode 和 ctx.Stop() 配合卡死。











