.NET 8+gRPC环境下无需安装根CA使用自定义CA实现mTLS
解决方案:无需安装CA到系统存储实现mTLS认证
问题根源
你遇到的核心问题是Kestrel的客户端证书验证与CertificateAuthentication中间件的验证是两个独立环节:
- 你已经在Kestrel层面通过自定义链逻辑验证了客户端证书,但CertificateAuthentication中间件会独立执行自身的证书链验证流程,默认依赖系统信任存储。因此即使Kestrel放行了请求,中间件仍会因自定义CA不在系统信任根中触发
OnAuthenticationFailed回调。
方案一:完全接管CertificateAuthentication的验证逻辑
关闭中间件默认的链验证,直接复用你已验证有效的自定义链逻辑:
builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme) .AddCertificate(options => { var caCert = new X509Certificate2("./certs/ca-cert.pfx"); options.AllowedCertificateTypes = CertificateTypes.Chained; // 关闭中间件默认的链验证,完全自定义验证逻辑 options.ValidateCertificateChain = false; options.ValidateValidityPeriod = true; options.RevocationMode = X509RevocationMode.NoCheck; options.Events = new CertificateAuthenticationEvents { OnCertificateValidated = context => { // 执行自定义链验证 var caChain = new X509Chain(); caChain.ChainPolicy.ExtraStore.Add(caCert); caChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; caChain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; bool isValid = caChain.Build(context.ClientCertificate); if (!isValid) { context.Fail("客户端证书链验证失败"); return Task.CompletedTask; } // 可选:添加证书身份校验,比如检查证书主题、颁发者等 // var certSubject = context.ClientCertificate.Subject; return Task.CompletedTask; }, OnAuthenticationFailed = context => { // 此处可记录失败日志 return Task.CompletedTask; }, }; });
方案二:配置中间件使用自定义信任根
若希望保留中间件的部分默认验证逻辑,只需指定其信任你的自定义CA作为根证书:
builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme) .AddCertificate(options => { var caCert = new X509Certificate2("./certs/ca-cert.pfx"); options.AllowedCertificateTypes = CertificateTypes.Chained; options.ValidateCertificateUse = true; options.ValidateValidityPeriod = true; options.RevocationMode = X509RevocationMode.NoCheck; // 设置自定义信任根模式,指定信任你的CA options.CertificateChainValidationMode = X509ChainTrustMode.CustomRootTrust; options.CustomTrustStore = new X509Certificate2Collection { caCert }; options.Events = new CertificateAuthenticationEvents { OnCertificateValidated = context => { return Task.CompletedTask; }, OnAuthenticationFailed = context => { return Task.CompletedTask; }, }; });
客户端配置补充
客户端(gRPC应用)也需要使用自定义CA验证服务器证书,避免因服务器证书不被系统信任而连接失败:
var handler = new HttpClientHandler(); var caCert = new X509Certificate2("./certs/ca-cert.pfx"); // 自定义服务器证书验证逻辑 handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { var customChain = new X509Chain(); customChain.ChainPolicy.ExtraStore.Add(caCert); customChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; customChain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; return customChain.Build(cert); }; // 添加客户端证书 handler.ClientCertificates.Add(new X509Certificate2("./certs/client1.pfx")); // 构建gRPC通道 var channel = GrpcChannel.ForAddress("https://your-server-url", new GrpcChannelOptions { HttpClient = new HttpClient(handler) });
内容的提问来源于stack exchange,提问作者Darc
相关产品推荐
相关产品推荐

