JWT解析失败后必须调用ctx.StopExecution()终止执行链,否则仅设401状态码和响应体仍会执行后续handler;须校验Bearer前缀、签名、过期及Issuer,并显式调用ctx.User.Set()绑定用户。

JWT 解析失败后必须调用 ctx.StopExecution(),不能只写 ctx.StatusCode(401)
很多开发者在中间件里发现非法 token 请求仍能进到业务 handler,根本原因是只设置了状态码和响应体,但没终止执行链。ctx.StatusCode(401) 和 ctx.JSON() 只是改响应,ctx.Next() 依然会继续往下走。正确做法是解析失败时立刻调用 ctx.StopExecution()(或旧版的 ctx.StopWithStatus(401)),确保后续 handler 完全不执行。
- 错误写法:
ctx.StatusCode(401); ctx.JSON(map[string]string{"error": "invalid token"}); ctx.Next()→ 业务逻辑照常运行 - 正确写法:
ctx.StatusCode(401); ctx.JSON(map[string]string{"error": "invalid token"}); ctx.StopExecution() - 别依赖
return:即使写了return,如果前面没调StopExecution,Iris 仍可能继续执行注册的下一个中间件或 handler
从 Authorization 头提取 token 要校验格式,不能硬拆字符串
ctx.Request().Header.Get("Authorization") 返回的是完整 header 值,比如 "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."。直接 strings.Split(header, " ") 并取第二段很危险——header 可能为空、缺空格、前缀不是 Bearer,甚至被篡改成 "Basic xxx"。
Token 消耗追踪工具。当用户需要监控 API token 使用情况、生成每日/每周消耗报告、分析使用趋势时使用此 Skill。功能包括:自动记录每次对话的 token 消耗、生成数据表格报告、计算使用趋势和预测、支持定时推送日报。
- 先检查是否以
"Bearer "开头(注意末尾空格):strings.HasPrefix(header, "Bearer ") - 再取子串:
tokenString := strings.TrimPrefix(header, "Bearer ") - 空字符串或长度过短(如
"Bearer ")直接视为非法,ctx.StopExecution() - 不要用
ctx.GetHeader("Authorization")替代ctx.Request().Header.Get()—— 后者更底层、更可靠
解析 token 时必须验证签名、过期、Issuer 等字段,漏一项就可能绕过
Iris 不做任何 JWT 校验,全靠你手动调用 jwt.Parse() 并传入完整验证逻辑。常见疏漏是只检查 Valid 字段,却忽略 Claims 结构体里的 ExpiresAt、IssuedAt、Issuer 等字段是否符合预期。
- 密钥必须从配置读取:
jwt.HmacSigningMethod.Sign(..., config.JWTSecret),硬编码"my-secret"等于把门钥匙贴在门上 - 用
jwt.ParseWithClaims(tokenString, &MyClaims{}, func(t *jwt.Token) (interface{}, error) { ... })显式传入 claims 类型和密钥函数 - 解析成功后,必须检查
claims.ExpiresAt.Time.After(time.Now()),否则过期 token 仍被放行 - 业务敏感接口建议校验
claims.Issuer == "my-app",防止其他服务签发的 token 滥用
ctx.User.Set() 必须在验证通过后显式调用,否则 ctx.User.Get() 总是 nil
ctx.User() 是个空接口占位符,Iris 不会自动填充。如果你在中间件里解析出用户 ID 或结构体,但没调 ctx.User.Set(&user),后续所有 handler 里调 ctx.User.Get() 都会得到 nil。
- user 类型可以是
struct、map[string]interface{}或任意实现了iris.User接口的类型 - 推荐定义具体结构体:
type User struct { ID uint64; Name string; Role string },避免 map 的类型不安全 - 别在中间件外赋值:比如在 login handler 里 set 一次,指望它跨请求生效——
ctx.User生命周期仅限当前请求 - 如果用了 Party 分组(如
admin := app.Party("/admin")),认证中间件必须注册在该分组上:admin.Use(authMiddleware),否则 /admin 下的路由不会触发校验
StopExecution 的调用时机,是 JWT 鉴权最易出错的两个点。一个漏掉,整个认证就形同虚设。

















