- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
几年前我编写了一个 Windows 服务来处理来自多个来源的数据,其中一个是第三方 SOAP Web 服务。它使用第三方提供的客户端证书通过此 Web 服务进行身份验证。这在当时运行良好,并且在部署它的原始机器上仍然运行良好,但现在他们正在迁移到一台新机器,连接尝试抛出异常并显示消息:
The HTTP request was forbidden with client authentication scheme 'Anonymous'
同样的事情现在也发生在我的开发机器上。这是配置与 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 来配置绑定(bind)。
可以向 ServicePointManager 类添加回调以执行服务器证书的自定义验证。在将客户端证书发送到服务器之前,客户端基类或绑定(bind)是否对客户端证书执行某些验证?如果是这样,有没有一种方法可以像服务器证书验证一样干预该过程,以便我可以看到发生了什么?
最佳答案
我找到了解决方案,但不确定我是否完全理解它。问题是客户端证书(或者可能只是链中的一些其他证书)需要出现在发出请求的用户的个人证书存储中。我以运行 Windows 服务的用户身份登录,将证书导入其存储区,现在一切正常。
这表明客户端证书以某种方式得到验证,即使它们是从文件加载而不是在商店中引用的。这实际上在 ProcMon 的输出中很明显,如果我更注意的话,我会意识到它正在搜索证书存储并得出 NOT FOUND 结果。
如果 Microsoft 的 WCF 客户端代码在证书有问题时抛出异常,而不是仅仅尝试在没有证书的情况下继续运行,那就太好了。嗯……
关于.net - 为什么我的客户端证书没有包含在 TLS 握手中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13125367/
我是一名优秀的程序员,十分优秀!