微服务间鉴权应统一在RPC框架或网关层实现,通过mTLS+Token双重校验,采用RBAC+Resource Action模型、白名单匹配、动态加载权限配置,并严格校验exp与权限范围。

微服务间调用必须走统一鉴权中间件
不建议在每个服务里重复实现权限逻辑,容易漏校验、版本不一致。Golang 微服务间鉴权的核心是把校验下沉到 RPC 框架层或网关层,让业务代码只关注「我能做什么」,不操心「我能不能做」。
典型做法是在 grpc.UnaryInterceptor 或 http.Handler 中统一拦截请求,解析并验证上游传来的认证凭证(如 JWT、Service Token)。关键点在于:凭证必须由可信方签发,且包含可验证的 service_id、permissions、exp 字段。
- 避免用明文
service_name做权限依据——容易被伪造 - JWT 的
iss字段应固定为中央认证服务地址,aud应明确指定目标服务名 - 签名密钥必须轮换,且不同环境(dev/staging/prod)使用不同密钥
Service Token 要带最小必要权限范围
微服务间调用不是「全服务信任」,而是「按需授权」。比如 order-service 调用 user-service 时,只应被授予 user:read:profile,而非 user:*。
推荐用 RBAC + Resource Action 模型编码权限,例如:
立即学习“go语言免费学习笔记(深入)”;
["user:read:profile", "user:update:email", "payment:query:by_order_id"]
校验时用白名单匹配,而非字符串前缀判断(避免 user:read 意外匹配到 user:read:profile:internal 这类敏感接口)。
- 权限列表应在服务启动时从配置中心加载,不硬编码在代码里
- 每次 RPC 请求携带的 Token 中
scope字段必须与调用方实际需要的权限严格一致 - 若 Token 权限不足,直接返回
status.Error(codes.PermissionDenied, "..."),不透出具体缺失哪条权限
不要依赖 HTTP Header 传递敏感鉴权信息
HTTP Header 容易被篡改或日志误打,X-Service-Token、X-Auth-Permissions 这类自定义头不能作为唯一校验依据。
正确做法是:所有服务间通信强制走 mTLS,再叠加 Token 校验。mTLS 解决「谁在调用」,Token 解决「能调什么」。
- gRPC 默认支持
credentials.TransportCredentials配置双向证书 - HTTP 服务可用
http.Server.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert - Header 中只传非敏感上下文(如
X-Request-ID、X-Trace-ID),鉴权字段全部从 TLS 连接元数据或解密后的 Token 中提取
本地开发和测试环境必须模拟真实鉴权链路
很多团队在本地用 skipAuth = true 启动服务,结果上线后才发现权限字段缺失、Token 解析失败、过期时间单位错用(秒 vs 毫秒)等问题。
建议在 dev 环境部署轻量级本地 Auth Server(如用 github.com/golang-jwt/jwt/v5 写一个 50 行的签发接口),所有服务启动时通过环境变量 AUTH_URL=http://localhost:8081 获取 Token。
- 测试用例必须覆盖
invalid token、expired token、missing permission三类错误路径 - Mock Server 不要直接返回
200 OK,而要模拟真实鉴权失败响应(如401 Unauthorized或403 Forbidden) -
go test运行时加-tags=auth控制是否启用校验,避免 CI 和本地行为不一致
exp 字段的系统时钟偏移,以及服务重启后未刷新缓存的权限白名单。这两处没有日志、不报 panic,但会导致权限静默失效或长期有效。










