【发布时间】:2012-10-29 16:08:08
【问题描述】:
几年前我编写了一个 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 服务,但 Visual Studio 在从 WSDL 自动生成客户端代码时似乎并不介意。客户端证书是从文件而不是从证书存储中加载的。所有机器上都在使用相同的证书文件,并且在单步执行代码时似乎可以正常加载。
我比较了使用 WireShark 的机器发出的请求与我的开发机器发出的请求,并且客户端证书似乎没有包含在握手中:
这是来自有效机器上的请求的相应数据包:
有很多关于 WCF、SOAP 和密码学的内容我不了解,因此对于导致这种行为的环境可能有什么不同以及需要更改哪些内容来纠正,我有点茫然它。
This question 似乎是相关的,但我似乎无法通过代码访问任何 RequireClientCertificate 属性,并且我没有使用 app.config 来配置绑定。
可以向 ServicePointManager 类添加回调,以执行服务器证书的自定义验证。在将客户端证书发送到服务器之前,基客户端类或绑定是否对客户端证书进行了一些验证?如果是这样,我是否可以像处理服务器证书验证一样干预该过程,以便查看发生了什么?
【问题讨论】:
-
只是为了确保您上面的代码确实可以在旧机器上运行,但不能在新机器上运行?
-
这是正确的 iMortalitySX。从那以后,我已经在另外几台机器上尝试过它,但也无法让它在这些机器上运行。
-
你能拼凑一个虚拟应用程序并添加一个“Web Reference”而不是“Service Reference”吗?这应该可以创建一个快速应用来测试您是否可以与该服务进行通信。
-
好主意,我稍后会尝试并返回结果。感谢您的所有帮助!
-
出于某种原因,Visual Studio 不会从 Web 服务的 WSDL 自动生成 Web 引用的客户端代码。我决定继续在测试应用程序中重新创建 WCF 服务引用,认为无论如何进行试验会更容易。我重新创建了引用,并在 app.config 中重新创建了绑定,而不是在代码中,并且......它连接了!我不知道该笑还是该哭……
标签: .net vb.net wcf soap wcf-security