使用 TLS 1.2 的自定义 X509CertificateValidator

Custom X509CertificateValidator with TLS 1.2

我在使用 TLS 1.2 时遇到自定义证书验证器的问题

我通过继承 X509CertificateValidator 并实现 Validate() 函数来设置自定义验证器。

但是,由于某些原因,Validate() 函数从未被调用,我的客户收到错误消息:

The caller was not authenticated by the service

内部异常:

The request for security token could not be satisfied because authentication failed.

这适用于 TLS 1.0(启用后,我可以在 Validate() 中设置一个断点,它会被命中,但被禁用时,它不会。)

根据其他问题的建议,我尝试在客户端和服务器中添加:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

...这在客户端的配置文件中:

<AppContextSwitchOverrides value="Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols=false;Switch.System.Net.DontEnableSchUseStrongCrypto=false;;Switch.System.Net.DontEnableSystemDefaultTlsVersions=false" />

... 在服务器的 web.config 文件中:

<add key="AppContext.SetSwitch:Switch.System.Net.DontEnableSchUseStrongCrypto" value="false" />
<add key="AppContext.SetSwitch:Switch.System.Net.DontEnableSystemDefaultTlsVersions" value="false" />

这是创建自定义验证器的代码:

    protected override void ApplyConfiguration()   // Overrides ServiceHost.ApplyConfiguration()
    {

        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

        base.ApplyConfiguration();

        var binding = new MyAppHttpBinding();    // Custom object inheriting from CustomBinding - See below...

        AddServiceEndpoint(typeof(IMyService), binding);

        Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom;

        var configuration = WebConfigurationManager.OpenWebConfiguration("~");
        var clientCertificate = configuration.GetCertificate("MyApp.ClientCertificate");
        var serviceCertificate = configuration.GetCertificate("MyApp.ServerCertificate");

        Credentials.ClientCertificate.Authentication.CustomCertificateValidator = new ThumbprintCertificateValidator(new[] { clientCertificate });
        Credentials.ServiceCertificate.Certificate = serviceCertificate;
    }

... 和 Validate() 函数...

(仅使用 TLS 1.2 似乎无法解决这个问题)

   public void Validate(string thumbprint)
   {
        var valid = Thumbprints
            .Contains(thumbprint);

        if (!valid)
        {
            throw new SecurityTokenValidationException("Certificate thumbprint does not match any in certificate store.");
        }
    }

    /// <summary>
    /// Validates the certificate's thumbprint with those specified.
    /// </summary>
    public override void Validate(X509Certificate2 certificate)
    {
        var thumbprint = certificate.Thumbprint;

        Validate(thumbprint);
    }

这是从其构造函数

调用的MyAppHttpBinding的初始化代码
        var sslNegotiationBindingElement = SecurityBindingElement.CreateSslNegotiationBindingElement(true);

        sslNegotiationBindingElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;

        var secureConversationBindingElement = SecurityBindingElement.CreateSecureConversationBindingElement(sslNegotiationBindingElement);

        Elements.Add(new TransactionFlowBindingElement());
        Elements.Add(secureConversationBindingElement);
        Elements.Add(new TextMessageEncodingBindingElement());
        Elements.Add(new HttpTransportBindingElement());

要使用 TLS,请参阅文档 Transport Layer Security (TLS) best practice with the .NET Framework
1.For TLS 1.2,在您的应用程序上定位 .NET Framework 4.7 或更高版本,在您的 WCF 应用程序上定位 .NET Framework 4.7.1 或更高版本。
在下面的示例中,将 4.7.2 替换为您当前使用的任何版本的框架 >= 4.7

<system.web>
       <compilation targetFramework="4.7.2"></compilation>
       <httpRuntime targetFramework="4.7.2" />
</system.web>

2.It建议不要指定TLS版本。配置您的代码,让 OS 决定 TLS 版本。 3.One截图代码中多写了符号(;),客户端和服务端的配置尽量保持一致
https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/appcontextswitchoverrides-element