我正在开发一个尝试与服务器建立安全连接的 .NET 服务。该服务不知道服务器是否支持安全连接。这就是为什么我只是尝试建立安全连接,如果失败,我将退回到不安全的连接。
我将 TcpClient
与 SslStream
一起使用:
tcpClient.BeginConnect(hostname, port, Start, null);
private void Start(IAsyncResult asyncResult)
{
X509CertificateCollection certCollection = new X509CertificateCollection();
certCollection.Add(new X509Certificate2("cert.p12", "pw"));
SslStream sslStream = new SslStream(tcpClient.GetStream(), false, new RemoteCertificateValidationCallback(ValidateCertificate));
sslStream.ReadTimeout = 2000;
sslStream.BeginAuthenticateAsClient("name", certCollection, SslProtocols.Tls, false, AuthenticateCallback, sslStream);
}
private void AuthenticateCallback(IAsyncResult asyncResult)
{
stream.ReadTimeout = -1;
// secure connection has been established
}
如果服务器不支持请求的加密,则在调用回调方法之前需要 2 分钟。使用同步方法
AuthenticateAsClient()
而只需要预期的 2 秒(根据设置 ReadTimeout
的要求):sslStream.AuthenticateAsClient("ESLD Server", certCollection, SslProtocols.Tls, false);
为什么超时只适用于同步方法?
如何减少异步方法的回调时间?
或者是否有更好的方法来检查服务器是否支持安全连接?
最佳答案
我无法给出明确的答案,只是扩展我在这方面遇到的一些问题。
您尝试使用的是什么操作系统?
我发现,如果客户端连接是通过异步调用(带有回调的 BeginXxxx)设置的,相互身份验证在 Windows XP 上运行良好,但我无法在 Windows 7 或更高版本上运行。同步方法在 XP 到 8.1 中都可以正常工作,但异步方法在除 XP 之外的所有系统上都会产生最奇怪的结果。
在 Windows 7 中,就好像您在 BeginAuthenticateAsClient 中传递的证书永远不会到达另一端。 SslStream 构造函数设置的远程证书验证回调为证书和链参数获取 Null,为 SslPolicyErrors 参数获取 RemoteCertificateNotAvailable。
使用 AuthenticateAsClient 而不是 [BeginAuthenticateAsClient + callback],问题就解决了。
在 Windows 8.1 中,情况更奇怪:当我在那里运行完全相同的代码时,在远程调用 SslStream 构造函数设置的远程证书身份验证回调之前,调用了对 BeginAuthenticateAsClient 的回调,表明身份验证过程已完成,因此服务器应用程序还没有机会接受或拒绝客户端证书。
关于c# - 超时 : BeginAuthenticateAsClient vs AuthenticateAsClient,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22097898/