电话
400 9058 355
推荐采用mTLS+JWT混合方案:用mTLS保障传输安全,JWT由统一授权中心签发并用RS256签名,服务启动时加载公钥,校验时严格匹配iss、aud、exp,并通过X-Service-Token传递,gRPC场景使用PerRPCCredentials透传。
单纯靠 JWT 做服务间鉴权不安全,必须配合传输层加密。Golang 微服务间通信推荐 mTLS(双向 TLS)兜底传输安全,再叠加 JWT 做服务身份断言。关键不是“要不要 JWT”,而是“JWT 由谁签发、怎么校验、何时刷新”。
issuer 必须是统一的内部授权中心(如自建 authz-svc),所有服务只信任该 issuer 的公钥issuer public key(PEM 格式),避免硬编码或每次远程拉取aud 字段必须显式设为被调用服务名(如 "user-service"),校验时严格比对,防止 token 被跨服务复用HS256;一律用 RS256 或 ES256,私钥仅存于授权中心,服务端只持公钥HTTP 中间件需区分「外部请求」和「内部服务请求」。不能把面向用户的 JWT 校验逻辑直接套用到服务间调用上——它们的签发源、有效期、scope 都不同。

X-Service-Token,而非复用 Authorization: Bearer xxx
req.TLS != nil && len(req.TLS.PeerCertificates) > 0,确保 mTLS 已建立,否则直接拒绝github.com/golang-jwt/jwt/v5,注意 ParseWithClaims 必须传入自定义 jwt.MapClaims 并手动验证 iss、aud、exp
401 Unauthorized,且响应体不要暴露细节(如不说明是 exp 过期还是 aud 不匹配)func ServiceAuthMiddleware(pubKey *rsa.PublicKey) gin.HandlerFunc {
return func(c *gin.Context) {
tokenStr := c.GetHeader("X-Service-Token")
if tokenStr == "" {
c.AbortWithStatus(http.StatusUnauthorized)
return
}
token, err := jwt.ParseWithClaims(tokenStr, &jwt.MapClaims{}, func(t *jwt.Token) (interface{}, error) {
if _, ok := t.Method.(*jwt.SigningMethodRSA); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"])
}
return pubKey, nil
})
if err != nil || !token.Valid {
c.AbortWithStatus(http.StatusUnauthorized)
return
}
claims, ok := token.Claims.(jwt.MapClaims)
if !ok || claims["iss"] != "https://authz.internal" || claims["aud"] != "order-service" {
c.AbortWithStatus(http.StatusUnauthorized)
return
}
c.Next()
}
}
gRPC 没有 HTTP 头概念,服务间认证必须走 credentials.PerRPCCredentials 接口。别试图在 UnaryInterceptor 里解析 metadata 手动校验——那会绕过 transport 安全边界。
GetRequestMetadata,从本地缓存读取有效期内的 JWT(避免每次调用都生成新 token)grpc.Creds(credentials.NewTLS(...)) 强制启用 mTLS,再在 interceptor 中提取 metadata.MD 并校验 X-Service-Token 对应的 JWTSubject.CommonName 动态签发,防伪造API 网关(如 Kong、Traefik)适合做流量路由和基础鉴权(如 API Key),但服务间细粒度权限(如 “order-service 是否允许调用 inventory-service 的 /v1/stock/deduct”)必须由被调用方自己判断。
service-policy.json 或从配置中心拉取 RBAC 规则,规则粒度到 service:action(如 "payment-service:charge")sub(调用方服务名)和 scope(声明的能力列表),查表比对当前接口是否在允许范围内sub、aud、requested path 即可,不记录完整 token,防止密钥泄露
邮箱:8955556@qq.com
Q Q:8955556
本文详解如何将Go官方present工具(用于生成HTML5...
PySNMP在不同版本中对SNMP错误状态(errorSta...
time.Sleep仅阻塞当前goroutine,其他gor...
PHPfopen()创建含特殊符号的文件名失败主因是操作系统...
WooCommerce中通过代码为分组产品动态聚合子商品的属...
io.ReadFull返回io.ErrUnexpectedE...
本文详解Yii2中控制器向视图传递ActiveRecord数...
本文详解为何通过wp_set_object_terms()为...
Pytest中使用@mock.patch类装饰器会导致补丁泄...
带缓冲的channel是并发安全的FIFO队列;make(c...