身份验证中间件必须通过use在路由匹配前全局注册才能生效,userouter仅作用于子路由;需从authorization头提取jwt并校验签名、exp及用户状态,解析结果应缓存至ctx.values(),同时处理options预检请求并避免与token刷新逻辑耦合。

中间件注册顺序决定身份验证是否生效
在 Iris 中,Use 和 UseRouter 的调用顺序直接影响中间件执行时机。身份验证中间件必须在路由匹配前执行,否则可能跳过校验。常见错误是把鉴权逻辑写在 Get/Post 回调里,或误用 UseRouter 导致仅对子路由生效。
-
Use:全局应用,所有请求(包括未匹配路由)都会经过,适合做统一鉴权 -
UseRouter:只作用于当前路由器及其子路由,适合模块级权限控制(如/admin/*) - 若需对部分路由放行(如登录接口),应在中间件内显式跳过,而不是依赖路由注册顺序“绕过”
从 Authorization Header 提取并验证 JWT
典型场景是读取 Authorization: Bearer <token></token>,解析 JWT 并检查签名、过期时间与用户状态。Iris 本身不内置 JWT 解析,需搭配 github.com/golang-jwt/jwt/v5 或 github.com/kataras/iris/v12/middleware/jwt(官方维护但较旧)。
关键点:
- 务必校验
exp字段,避免使用已过期 token - 建议用
jwt.ParseWithClaims指定自定义jwt.Claims结构体,便于提取user_id、role等字段 - 解析失败时应直接调用
ctx.StopWithStatus(401),而非返回空值让后续逻辑崩溃 - 不要在中间件里重复解析 token——Iris 的
ctx.Values().Set可缓存解析结果供 handler 使用
authMiddleware := func(ctx iris.Context) {
authHeader := ctx.GetHeader("Authorization")
if authHeader == "" || !strings.HasPrefix(authHeader, "Bearer ") {
ctx.StopWithStatus(iris.StatusUnauthorized)
return
}
tokenStr := strings.TrimPrefix(authHeader, "Bearer ")
token, err := jwt.ParseWithClaims(tokenStr, &UserClaims{}, func(t *jwt.Token) (interface{}, error) {
return []byte("your-secret-key"), nil
})
if err != nil || !token.Valid {
ctx.StopWithStatus(iris.StatusUnauthorized)
return
}
claims := token.Claims.(*UserClaims)
ctx.Values().Set("user_id", claims.UserID)
ctx.Next()
}
结合数据库或 Redis 校验 token 黑名单或会话有效性
JWT 默认无状态,但业务常需支持主动登出、强制刷新或临时封禁。这时不能只依赖签名和过期时间,必须查存储层。
- 若用 Redis 存 token 黑名单,建议以
"blacklist:" + sha256(token)为 key,设置 TTL 略大于 token 过期时间 - 若查数据库验证用户状态(如
is_active = true),注意加索引到user_id和status字段,避免每次鉴权都触发全表扫描 - 推荐在中间件中使用
ctx.Values().Set("user", user)而非全局变量,避免并发请求间数据污染 - 别在中间件里做耗时 DB 查询后不设超时——Iris 不自动中断慢中间件,可能拖垮整个服务
处理 OPTIONS 预检请求避免鉴权拦截
CORS 预检请求(OPTIONS)不含 Authorization 头,若中间件未特殊处理,会导致前端跨域请求直接 401。
- 在鉴权中间件开头加判断:
if ctx.Method() == "OPTIONS" { ctx.Next(); return } - 更稳妥的做法是用 Iris 官方
iris.CORS中间件,并确保它注册在鉴权中间件之前(app.Use(iris.CORS())→app.Use(authMiddleware)) - 注意:CORS 中间件默认不放行
Authorization头,需显式配置iris.CORS().AllowHeaders("Authorization")
/refresh 接口,并在该接口里校验旧 token、签发新 token、更新存储状态。强行把刷新塞进鉴权中间件,会导致所有请求都尝试刷新,破坏幂等性。











