You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 19:29:50