使用 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
我在使用 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