如何在gRPC服务端获取客户端SSL证书信息
gRPC 服务端无法获取客户端证书的解决方案
问题根因
你遇到的现象是gRPC服务端默认未开启双向TLS(mTLS)的客户端证书校验策略:
默认创建SslServerCredentials时,客户端证书请求策略为不请求模式,即使客户端主动携带了证书,服务端也会忽略该证书、不会做校验,也不会将证书信息写入AuthContext,因此你无法从AuthContext中读到客户端证书相关字段。你之前观察到TLS握手正常,是因为此时走的是仅客户端校验服务端证书的单向TLS流程,不需要服务端校验客户端证书也能完成握手。
缺失的核心配置
你需要在构建服务端SslServerCredentials时,显式开启强制客户端证书校验,同时传入用来校验客户端证书合法性的CA根证书(你自签名体系的根证书)。不同语言的配置示例如下:
- Go 语言
import ( "crypto/tls" "crypto/x509" "os" "google.golang.org/grpc/credentials" ) // 加载服务端自身证书密钥 serverCert, err := tls.LoadX509KeyPair("server.crt", "server.key") // 加载用来校验客户端证书的CA根证书 caCert, err := os.ReadFile("ca.crt") certPool := x509.NewCertPool() certPool.AppendCertsFromPEM(caCert) // 核心配置:指定客户端校验策略为强制校验 creds := credentials.NewTLS(&tls.Config{ Certificates: []tls.Certificate{serverCert}, ClientCAs: certPool, ClientAuth: tls.RequireAndVerifyClientCert, })
- Java 语言
import io.grpc.netty.GrpcSslContexts; import io.netty.handler.ssl.ClientAuth; import io.netty.handler.ssl.SslContext; import java.io.File; SslContext sslContext = GrpcSslContexts.forServer( new File("server.crt"), new File("server.key") ) .trustManager(new File("ca.crt")) // 客户端证书的CA根证 .clientAuth(ClientAuth.REQUIRE) // 核心配置:强制要求客户端证书 .build();
- Python 语言
import grpc # 加载服务端证书密钥 with open("server.key", "rb") as f: server_key = f.read() with open("server.crt", "rb") as f: server_cert = f.read() # 加载客户端CA根证 with open("ca.crt", "rb") as f: ca_cert = f.read() # 核心配置:开启require_client_auth creds = grpc.ssl_server_credentials( private_key_certificate_chain_pairs=[(server_key, server_cert)], root_certificates=ca_cert, require_client_auth=True )
配置验证
修改配置重启服务端后,客户端证书的PEM格式内容会存储在AuthContext的x509_pem_cert属性中,可直接通过对应语言的AuthContext读取接口获取该值。
内容的提问来源于stack exchange,提问作者cd606
相关产品推荐
相关产品推荐

