Authorization头解析错误导致JWT验证失败:需用req.Header.Get("Authorization")、剥离Bearer前缀、显式校验exp/nbf、匹配算法与密钥类型、结构体字段首字母大写并加json tag。

Authorization头没取对,req.headers.authorization为空或格式错
Echo里默认不自动解析Authorization头,很多开发者直接写req.Header.Get("authorization")——小写字段名在某些HTTP代理或测试工具下会丢失。更常见的是token带了Bearer 前缀但没剥离,后续传给jwt.ParseWithClaims时直接panic。
实操建议:
- 统一用
req.Header.Get("Authorization")(首字母大写),避免大小写歧义 - 必须检查是否以
"Bearer "开头,再用strings.TrimSpace(tokenStr[7:])提取,别用split(" ")——万一token本身含空格就裂开 - 加个日志:
log.Printf("raw auth header: %q", req.Header.Get("Authorization")),确认前端真传了东西
jwt.ParseWithClaims返回token.Valid == false但err == nil
这是Echo+JWT最隐蔽的坑:验证失败不报错,token.Valid默默变false,后续token.Claims类型断言直接panic。根本原因常是exp/nbf时间校验被跳过,或密钥加载逻辑没触发。
实操建议:
- 调用
jwt.ParseWithClaims时,显式传入jwt.WithExpirationRequired()和jwt.WithValidMethods([]string{"HS256"}),强制校验关键项 - 在
keyFunc里第一行加log.Println("keyFunc called"),如果没打印,说明token字符串本身非法(比如少了一个.、base64url填充缺失) - 别只依赖
err != nil判断,一定要加if !token.Valid { return echo.NewHTTPError(http.StatusUnauthorized, "invalid token") }
密钥类型或加载方式错配,HS256和RS256混用
Header里写着"alg": "HS256",但keyFunc返回的是RSA公钥;或者反过来,用对称密钥去验RS256签名——两者完全不兼容,ParseWithClaims会静默失败。
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
实操建议:
- 先用
token.Method.Alg()打印实际算法,和Header里声明的比对,不一致立刻终止 - 对称算法(
HS256)密钥必须是[]byte,且长度≥32字节;RSA密钥必须是*rsa.PublicKey,且PEM块要完整(含-----BEGIN PUBLIC KEY-----) - 别从环境变量直接读RSA密钥字符串——需用
pem.Decode解析后转公钥,否则jwt.Parse会认为密钥无效
自定义Claims结构体字段没导出,sub/user_id取不到
明明token解码成功,token.Valid == true,但claims.(CustomClaims).UserID是空,甚至panic。问题八成出在结构体字段未导出,JSON反序列化失败。
实操建议:
- 自定义Claims结构体字段名首字母必须大写,且带
jsontag,例如:UserID string `json:"user_id"` - 别用
map[string]interface{}接Claims——类型擦除后无法安全取值,强制用结构体 - 验证时加一行
log.Printf("raw claims: %+v", claims),看字段名是否匹配tag,避免大小写或下划线错位
时间偏移、密钥加载时机、结构体导出规则——这些点不打日志根本看不见,等报401再查,已经绕远了。










