Iris中Authorization头为空因未手动提取Bearer前缀;JWT验签失败常因缺失exp字段或类型错误;中间件默认拦截所有路由需用Except排除登录接口;自定义Claims须嵌入RegisteredClaims并加json tag。

iris.Context.GetHeader("Authorization") 提取 token 时为什么总为空?
因为 Iris 默认不自动解析 Authorization 头里的 Bearer token,必须手动提取并去掉前缀。常见错误是直接调用 c.GetHeader("Authorization") 后拿整个字符串去解析,结果 JWT 库报 invalid token 或签名错误。
正确做法是:先检查头是否存在,再按空格分割、校验前缀、取第二段:
auth := c.GetHeader("Authorization")
if auth == "" {
c.StatusCode(401)
c.JSON(map[string]string{"error": "missing Authorization header"})
return
}
var tokenString string
if strings.HasPrefix(auth, "Bearer ") {
tokenString = strings.TrimPrefix(auth, "Bearer ")
} else {
c.StatusCode(401)
c.JSON(map[string]string{"error": "Authorization header must start with Bearer "})
return
}注意:strings.TrimPrefix 比 strings.Split(auth, " ")[1] 更安全——避免空格过多或格式异常导致 panic。
jwt.ParseWithClaims 时提示 “token is expired” 却没设过期时间?
这是 JWT 标准字段 exp 的验证行为。即使你没显式写入 exp,某些 JWT 库(如 github.com/golang-jwt/jwt/v5)在解析时仍会检查它;而 Iris 自带的 iris/jwt 中间件默认开启严格验证,只要 token 里没 exp 或值非法,就拒绝。
生成 token 时务必设置 exp,推荐用 time.Now().Add(24 * time.Hour) 转为 Unix 时间戳:
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"sub": "123",
"exp": time.Now().Add(24 * time.Hour).Unix(), // 必须是 int64
})
signedToken, err := token.SignedString([]byte("your-secret-key"))
if err != nil {
c.StatusCode(500)
return
}容易踩的坑:
-
exp字段名不能写成expires或expiration—— JWT 规范只认exp - 值必须是
int64类型的 Unix 秒级时间戳,不是time.Time或字符串 - 密钥长度建议 ≥ 32 字节,否则
SigningMethodHS256可能被警告弱密钥
iris/jwt.New 配置中间件后,/login 接口也被拦截了?
因为 iris/jwt.New 默认对所有注册路由生效,包括登录接口。如果不排除,会导致登录请求因无 token 被 401 拦截,形成死循环。
解决方法是显式跳过指定路径,用 Except 方法:
jwtHandler := iris/jwt.New(iris/jwt.Config{
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
return []byte("your-secret-key"), nil
},
SigningMethod: jwt.SigningMethodHS256,
})
jwtHandler.Except("/login", "/register") // 注意路径前缀是否带 /注意点:
-
Except接收的是完整匹配路径,不支持通配符(如/api/*),需逐个列出免检接口 - 如果用了子路由器(
app.Party("/api")),Except里的路径要和注册时一致(如/api/login) - 不要把
jwtHandler放在全局Use,而是按需挂到具体 Party 或路由组上
自定义 Claims 结构体解析失败,提示 “json: cannot unmarshal object into Go struct field”?
这是因为解析时传入的 Claims 类型与 token payload 实际结构不一致。比如 token 里存了 "user_id": 123,但你的结构体字段叫 UserID 却没加 JSON tag,Go 默认找 userid 字段。
正确方式是定义结构体并显式绑定字段名:
type MyClaims struct {
jwt.RegisteredClaims
UserID uint `json:"user_id"`
Username string `json:"username"`
}
// 解析时:
claims := &MyClaims{}
_, err := jwt.ParseWithClaims(tokenString, claims, func(t *jwt.Token) (interface{}, error) {
return []byte("your-secret-key"), nil
})
if err != nil {
c.StatusCode(401)
return
}关键细节:
- 必须嵌入
jwt.RegisteredClaims(v5 版本),不能只用jwt.StandardClaims(v3/v4 已弃用) - 所有自定义字段都要有
json:tag,且值与 token 中 key 完全一致(大小写敏感) - 如果 token 是用
MapClaims生成的,就别用结构体解析——类型不匹配会直接失败
Iris 对 JWT 的支持依赖底层库(v5 推荐),密钥管理、时钟偏移、多签发者等复杂场景需要自己补全逻辑,别指望中间件全自动处理。


















