应先用r.Header.Get("Authorization")获取头,检查是否为空并Trim空格,再按空格切分校验前缀为"Bearer "且长度≥2,最后安全解析JWT;避免大小写混淆和非法格式。

怎么从 Authorization 头里安全取到 Bearer Token
直接用 r.Header.Get("Authorization") 拿值,但别急着用——它可能为空、格式错、带空格或混入其他认证类型。
- 先检查头是否存在:
r.Header.Get("Authorization")返回空字符串时直接拒掉,别往下 parse - 按空格切分前先 trim:有些客户端会发
"Bearer abc123"(前面有空格),用strings.TrimSpace()清理再切 - 切完必须校验长度:至少两段,第一段是
"Bearer"(大小写敏感),第二段才是 token;少于两段就返回 401 - 别用
strings.SplitN(header, " ", 2)以外的方式切——避免 token 本身含空格被误切(虽然少见,但 JWT 里 base64url 编码不含空格,所以安全)
为什么不能直接用 http.Request.Header.Get 后就 decode JWT
因为 Get 不区分大小写,但语义上 Authorization 是标准头,而实际请求中可能有 authorization、AUTHORIZATION 或拼写错误的 Authrization。Go 的 http.Header 内部做了规范化,所以 Get("Authorization") 能覆盖多数情况,但仍有隐患:
- 某些代理或网关会重写头名,比如转成
X-Forwarded-Authorization,这时原头已丢失 - 测试时用 curl 手动加头,容易漏写
-H "Authorization: Bearer ..."中的冒号或空格,导致取到空值却没报错 - JWT decode 前必须确认 token 非空且长度合理(比如短于 10 字符基本可判无效),否则
jwt.Parse可能 panic 或返回模糊错误
Bearer 和 Basic 共存时怎么避免误判
一个请求理论上只能有一种认证方案,但现实中前端可能错发两个头,或后端中间件叠加了不同认证逻辑。此时靠头名判断不保险,得看内容:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 如果
Authorization以"Basic "开头(注意空格),立刻跳过 Bearer 流程,别尝试 base64 解码后再比对 - 不要写
if strings.HasPrefix(auth, "Bearer")——这会把"BearerToken=xxx"这种非法值也放过,必须严格匹配"Bearer "(带空格) - 更稳妥的做法是先正则匹配:
^Bearer\s+([A-Za-z0-9_\-\.~\+\/]+=*)$,过滤掉明显非法字符(如换行、控制符),再传给 JWT 库
Token 校验失败时该返回什么 HTTP 状态和 Header
401 是标准响应,但光状态码不够,客户端需要明确知道问题出在哪:
立即学习“go语言免费学习笔记(深入)”;
- token 不存在或格式错 →
401 Unauthorized+WWW-Authenticate: Bearer realm="api" - token 过期或签名无效 → 同样 401,但不要暴露细节(比如别说 “expired”,避免泄露服务时间)
- 别返回 403:那是权限不足,不是认证失败;混淆两者会让前端无法正确刷新 token
- 开发阶段可在 response body 里加简短提示(如
{"error": "invalid_token"}),但生产环境建议只留状态码和标准 header

















