token鉴权不能只靠中间件拦截,因为http请求头中的authorization仅在入口存在,下游grpc/http调用无法自动继承;必须由中间件解析后显式将用户身份注入context,并在发起下游请求时手动透传至metadata或http header,否则下游视为未登录。

Token鉴权为什么不能只靠中间件拦截
因为真实服务链路里,HTTP 请求进来的 Authorization 头只在入口处存在;下游服务调用(比如 gRPC、HTTP 内部转发、消息队列消费)根本拿不到原始请求头。硬塞进 context 传下去?Go 的 context.Context 默认不跨进程,也不自动透传到 HTTP header 或 gRPC metadata。不显式传播,下游一概视为“未登录”。
实操建议:
- 入口中间件解析
Authorization: Bearer <token></token>后,必须把用户 ID、角色、过期时间等关键字段解出,存入context.WithValue——但仅限当前 goroutine 生命周期 - 所有向外发起的下游调用(
http.Client.Do、grpc.Invoke、amqp.Publish)前,必须手动把 token 或用户身份信息注入请求载体 - 避免在 context 里存结构体指针或大对象,容易引发内存泄漏;推荐存
string(如user_id)或轻量struct{UID string; Role string}
HTTP 服务间传播 Token 的三种写法与取舍
下游服务不是你写的?那必须带 Authorization 头;如果是自己控制的 Go 服务,可选更轻量的方式。
实操建议:
- 标准方式(兼容性最强):
req.Header.Set("Authorization", "Bearer "+token)——适用于调任何 HTTP 服务,但需确保 token 未过期且有对应 scope - 内部服务专用(省解码开销):
req.Header.Set("X-User-ID", userID)+req.Header.Set("X-User-Role", role)——跳过 JWT 解析,但需双方约定信任链和 header 白名单 - 用
net/http.RoundTripper统一注入:实现自定义RoundTripper,在RoundTrip方法里自动补Authorization头,避免每个 client 调用都手写
gRPC 场景下 token 怎么透传才不丢
gRPC 默认不携带 HTTP header,必须用 metadata.MD 显式传递;且 server 端要用 grpc.Peer 或 metadata.FromIncomingContext 拿,不是从 http.Request 里读。
实操建议:
- 客户端发起调用前,构造 metadata:
md := metadata.Pairs("authorization", "Bearer "+token),再用grpc.Metadata(md)作为CallOption - 服务端在 handler 开头立刻提取:
md, ok := metadata.FromIncomingContext(ctx),然后md["authorization"]取值 ——别等进业务逻辑才取,context 可能被包装过 - 注意大小写:
metadatakey 默认小写,"Authorization"会被转成"authorization",所以客户端写"authorization",服务端也按小写取
JWT 解析失败时该返回什么错误码
401 和 403 都常见,但语义不同:401 表示凭证缺失或无效(token 格式错、签名验不过、过期),403 是凭证有效但权限不足。混用会导致前端无法区分重登 or 拒绝访问。
实操建议:
-
ParseUnverified先检查格式和结构,格式错(如非 base64url)直接http.StatusUnauthorized - 签名验证失败、过期(
ErrTokenExpired)、签发者不匹配(issuer不符)——统一返回http.StatusUnauthorized - token 有效但
claims["role"]不满足接口要求(如需要"admin"却是"user")——返回http.StatusForbidden - 别用
http.StatusInternalServerError掩盖 JWT 错误,会干扰可观测性;日志里至少记下jwt.ParseError.Error()
传播机制最难的不是怎么传,而是谁来负责校验、谁来负责续期、谁来兜底处理过期——这些边界一旦模糊,token 就会在某个环节静默失效。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











