几年前,我编写了一个 Windows 服务,它处理来自多个来源的数据,其中一个是第三方 SOAP Web 服务。它使用第三方提供的客户端证书通过此 Web 服务进行身份验证。这在当时运行良好,并且在它部署到的原始机器上仍然运行良好,但现在他们正在迁移到连接尝试引发异常并显示消息的新机器:
客户端身份验证方案“匿名”禁止 HTTP 请求
现在我的开发机器上也发生了同样的事情。这是配置与 Web 服务的连接的代码:
Friend Shared Function GetProperlyConfiguredConnection() As SEMOService.MIWebServiceClient
' Ensure that the settings are valid
ValidateSettings()
Dim destAddress As New System.ServiceModel.EndpointAddress(Url)
' The service uses SOAP 1.1 which is what BasicHttpBinding uses. WSHttpBinding uses SOAP 1.2.
'Dim destBinding As New System.ServiceModel.WSHttpBinding
Dim destBinding As New System.ServiceModel.BasicHttpBinding
With destBinding
.CloseTimeout = New TimeSpan(0, 1, 0)
.OpenTimeout = New TimeSpan(0, 1, 0)
.ReceiveTimeout = New TimeSpan(0, 10, 0)
.SendTimeout = New TimeSpan(0, 1, 0)
.BypassProxyOnLocal = False
.HostNameComparisonMode = ServiceModel.HostNameComparisonMode.StrongWildcard
.MaxBufferPoolSize = 524288
.MaxReceivedMessageSize = 2147483647
.MessageEncoding = ServiceModel.WSMessageEncoding.Text
.TextEncoding = System.Text.Encoding.UTF8
.UseDefaultWebProxy = True
.AllowCookies = False
With .ReaderQuotas
.MaxDepth = 32
.MaxStringContentLength = 2147483647
.MaxArrayLength = 50000000
.MaxBytesPerRead = 4096
.MaxNameTableCharCount = 16384
End With
.Security.Mode = ServiceModel.BasicHttpSecurityMode.Transport
.Security.Transport.ClientCredentialType = ServiceModel.HttpClientCredentialType.Certificate
End With
Dim wcfService As New SEMOService.MIWebServiceClient(destBinding, destAddress)
' Load the certificate from the specified file.
Dim keyData As Byte()
Dim keyFileInfo As New IO.FileInfo(SEMOServiceSettings.KeyFilePath)
Dim keyFileReader As New IO.BinaryReader(New IO.FileStream(SEMOServiceSettings.KeyFilePath, IO.FileMode.Open, IO.FileAccess.Read))
keyData = keyFileReader.ReadBytes(keyFileInfo.Length)
keyFileReader.Close()
Dim cert As New X509Certificates.X509Certificate2
cert = New X509Certificates.X509Certificate2(keyData, SEMOServiceSettings.KeyFilePassword)
wcfService.ClientCredentials.ClientCertificate.Certificate = cert
Return wcfService
End Function
它实际上不是 WCF Web 服务,但在从 WSDL 自动生成客户端代码时,Visual Studio 似乎并不介意。客户端证书是从文件而不是从证书存储中加载的。所有机器上都在使用相同的证书文件,并且在单步执行代码时似乎可以正常加载。
我将使用 WireShark 的机器发出的请求与我的开发机器发出的请求进行了比较,似乎客户端证书没有包含在握手中,而应该是:
这是来自有效机器上的请求的相应数据包:
有很多关于 WCF、SOAP 和密码学的内容我不了解,所以对于导致这种行为的环境可能有什么不同,以及需要改变什么来纠正它,我有点茫然。
这个问题似乎是相关的,但我似乎无法RequireClientCertificate
通过代码访问任何属性,并且没有使用 app.config 来配置绑定。
可以向 ServicePointManager 类添加回调,以执行服务器证书的自定义验证。在将客户端证书发送到服务器之前,基客户端类或绑定是否对客户端证书进行了一些验证?如果是这样,有没有一种方法可以以与服务器证书验证相同的方式干预该过程,以便我可以看到发生了什么?