必须手动用c.queryparam("token")提取jwt,因echo-jwt默认不解析query参数;需显式配置tokenlookupfuncs支持query,并做非空校验、点号计数、base64预检及时间容错校验。

Query参数传JWT时,c.QueryParam("token")必须在echo-jwt中间件前手动提取
echo-jwt/v4 默认只从 Authorization Header 或固定 Query key(如 token)中提取 token,但它**不会自动解析 query 参数并注入到 context**;更关键的是,它默认的 TokenLookupFuncs 仅在匹配成功后才触发解析,而失败时连日志都不打,容易误判为“没传 token”。
所以不能依赖“它自己会读 query”,得主动取、主动验、主动塞回 context(如果后续逻辑需要):
-
c.QueryParam("token")是唯一安全方式,别用c.Param()或c.FormValue() - 若 token 存在但格式非法(如缺点、base64 编码错),
echo-jwt会静默跳过,需额外校验长度和结构(如是否含两个点) - 提取后建议立即做基础合法性检查:
strings.Count(token, ".") == 2,避免无效字符串进 JWT 解析流程 - 若你用自定义
ParseTokenFunc,注意它接收的是原始 token 字符串,不是 header 或 query key 名
echo-jwt配置里必须显式启用token query 支持
默认 echo-jwt 的 TokenLookup 只认 Authorization: Bearer xxx,不看 query。要让它支持 ?token=xxx,必须重写 TokenLookupFuncs 数组,并确保顺序合理:
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
- 把 query 提取逻辑放在数组首位,否则 Header 优先匹配成功后就不再尝试 query
- 不要只写
func(ctx echo.Context) ([]string, error) { return []string{ctx.QueryParam("token")}, nil }—— 这样当 query 为空时会传空字符串给解析器,导致 panic - 正确写法是先判断非空:
if t := ctx.QueryParam("token"); t != "" { return []string{t}, nil } - 多个来源可共存,比如同时支持
Authorization和tokenquery,但要注意 fallback 逻辑:Header 失败才查 query
鉴权失败时,echo-jwt返回401 Unauthorized,但错误信息不可信
默认行为是直接返回 echo.ErrUnauthorized,HTTP 状态码 401,响应体为空或仅含默认消息。这对前端调试极不友好——你不知道是 token 过期、签名错、还是压根没传。
- 务必配置
ErrorHandler,捕获echo.HTTPError并补充细节:err.Message可能是 "token is expired" 或 "invalid signature" - 别在
ParseTokenFunc里直接return nil, echo.NewHTTPError(401, "xxx"),这会绕过echo-jwt的统一错误处理流 - 如果要用 query 传 token,建议加个白名单限制:只允许本地调试或特定域名调用,防止 token 泄露到 referer 或 CDN 日志
- 生产环境禁用 query 传 token:浏览器历史、代理日志、CDN 缓存都可能记录 URL,
AuthorizationHeader 更安全
Query传JWT和Header传JWT不能混用同一套密钥逻辑
表面上都是 token 字符串,但实际校验路径不同:query token 更容易被中间件、网关、CDN 截断或转义(比如空格变 +、斜杠被编码),而 Header 基本保持原样。
- 如果你在
KeyFunc里做了算法校验(如拒绝alg: none),query token 同样要走这套逻辑,别以为“反正我只用 HS256 就行” - Base64Url 解码失败时,
echo-jwt会返回 generic error,但真实原因是 query 参数被多次 URL decode 或截断,需在提取后做base64.RawURLEncoding.DecodeString()预检 - 时间校验(exp/nbf)必须开启,且容忍时钟偏差:
jwt.WithValidTimeFunc(func(t time.Time) bool { return time.Now().Add(5 * time.Second).After(t.Add(-5 * time.Second)) }) - 别忘了
c.Request().URL.Query().Get("token")和c.QueryParam("token")行为一致,但前者绕过 Echo 的 query 解析缓存,后者更可靠
Query 参数本质是 URL 的一部分,一旦进入日志、监控、CDN 或代理链路,token 就可能暴露。哪怕只是临时调试,也要意识到它比 Header 多一层泄露风险——这不是配置问题,是协议层约束。










