jwt中间件必须在路由注册前挂载,即app.use(jwtmiddleware())须在app.get()等之前执行;解析token需用parsewithclaims匹配自定义claims类型;校验失败时必须调ctx.stopexecution()中断流程,否则存在未授权访问风险。

JWT中间件必须在路由注册前挂载
中间件不会自动生效,Iris 的 Use 或 UseGlobal 必须在 iris.Get、iris.Post 等路由注册调用之前执行,否则请求根本不会经过该中间件。常见错误是把中间件写在所有路由定义之后,结果 token 校验形同虚设。
正确顺序示例:
app := iris.New()
app.Use(JWTMiddleware()) // ✅ 必须放这里
app.Get("/api/user", getUserHandler)
app.Post("/login", loginHandler)
解析 token 时要区分 Parse 和 ParseWithClaims
Iris 自带的 jwt 包(基于 github.com/dgrijalva/jwt-go)中,Parse 默认使用 MapClaims,但如果你自定义了 claims 结构体(比如加了 UserID uint 字段),就必须用 ParseWithClaims 并传入对应类型,否则字段取不到或类型断言失败。
典型问题现象:panic: interface conversion: jwt.Claims is map[string]interface {}, not *model.JwtClaims
- 用
ParseWithClaims(tokenString, &JwtClaims{}, keyFunc)替代Parse(tokenString, keyFunc) -
keyFunc返回的密钥必须与签发时一致,且不能硬编码在中间件里——建议从配置或环境变量读取 - 注意
SigningMethod匹配:HS256 就用jwt.SigningMethodHS256,ES256 需额外处理公私钥
中间件里如何统一返回 401 而不继续执行后续 handler
Iris 中间件通过 ctx.Next() 控制流程,但 JWT 校验失败时不能只写 ctx.StatusCode(401) 就结束——必须调用 ctx.StopExecution(),否则后续 handler 仍会执行,可能造成未授权的数据访问或重复响应。
关键逻辑片段:
if err != nil || !token.Valid {
ctx.StatusCode(iris.StatusUnauthorized)
ctx.JSON(iris.Map{"error": "invalid or expired token"})
ctx.StopExecution() // ❗缺了这句就是严重漏洞
return
}
ctx.Next()
-
ctx.StopExecution()是 Iris 中断中间件链的唯一可靠方式 - 不要用
return单独退出中间件函数——它只跳出当前函数,不影响后续 handler 执行 - 如果用了
ctx.Values().Set("user_id", claims.UserID),确保下游 handler 有判空逻辑,因为中间件可能已提前终止
刷新 token 场景下要注意双 token 或时间窗口设计
Iris 本身不提供 refresh token 内置支持,若需实现“访问 token 过期前自动刷新”,得自己设计策略。常见做法有两种,都容易踩坑:
- 双 token 模式:access token 短期(15min),refresh token 长期(7d),但 refresh token 必须存储在服务端(如 Redis)做黑名单管理,否则无法主动失效
- 滑动过期:每次合法请求后重签一个新 access token,并在响应头(如
X-Auth-Token)返回,前端需自动覆盖旧 token;但要注意并发请求可能导致 token 覆盖错乱 - 无论哪种,都别在 JWT payload 里存敏感信息(如密码哈希、权限列表),应只存 ID,权限查库获取
JWT 本质是无状态认证,一旦签发就无法中途作废——这是它和 session 最根本的区别,也是所有 refresh 逻辑绕不开的前提。











