【发布时间】:2014-09-02 03:40:16
【问题描述】:
我使用SmtpClient 通过使用 SSL 的 SMTP 服务器发送电子邮件。此 SMTP 服务器配置为使用自签名证书。
由于我无法在所有客户端计算机上安装证书,我添加了一个ServicePointManager.ServerCertificateValidationCallback 来为我们的自签名证书实施自定义验证。
但是,我只想在使用SmtpClient 时执行自定义验证,并在其他地方执行证书验证时恢复为默认行为。
由于回调是一个静态属性,我还应该确保回调不是由我用来发送电子邮件的线程调用的。
我想出了以下代码:
Private Shared _defaultServerCertificateValidationCallback As System.Net.Security.RemoteCertificateValidationCallback
Private Shared _overrideSmtpCertificateValidation As Boolean = False
Private Shared _callbackLocker As New Object()
Private Shared Function OurCertificateValidation(s As Object, certificate As Security.Cryptography.X509Certificates.X509Certificate, chain As Security.Cryptography.X509Certificates.X509Chain, sslPolicyErrors As Net.Security.SslPolicyErrors) As Boolean
SyncLock _callbackLocker
If _overrideSmtpCertificateValidation Then
_overrideSmtpCertificateValidation = False
Dim actualCertificate = Security.Cryptography.X509Certificates.X509Certificate.CreateFromCertFile("selfSignedSmtp.cert")
Return certificate.Equals(actualCertificate)
Else
'Should execute the default certificate validation.
Return _defaultServerCertificateValidationCallback(s, certificate, chain, sslPolicyErrors)
End If
End SyncLock
End Function
Public Sub SendMail()
_defaultServerCertificateValidationCallback = System.Net.ServicePointManager.ServerCertificateValidationCallback
System.Net.ServicePointManager.ServerCertificateValidationCallback = New System.Net.Security.RemoteCertificateValidationCallback(AddressOf OurCertificateValidation)
_overrideSmtpCertificateValidation = True
'Send mail using SMTP client here...
End Sub
此代码在发送电子邮件时应该做的是将默认ServerCertificateValidationCallback保留在变量中,标记要执行的自定义验证,在与SmtpClient相同的线程上执行自定义验证,防止其他线程使用SyncLock 执行自定义验证,然后恢复为默认行为并允许其他线程继续使用默认证书验证。
但是,ServerCertificateValidationCallback 默认设置为Nothing,因此我无法显式调用默认验证回调。
有什么我可以调用而不是 Return _defaultServerCertificateValidationCallback(s, certificate, chain, sslPolicyErrors) 来在需要时执行默认证书验证吗?
【问题讨论】:
标签: c# vb.net multithreading ssl smtpclient