4

サーバーへの安全な接続を確立しようとする .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);

タイムアウトが同期メソッドにのみ適用されるのはなぜですか? 非同期メソッドのコールバック時間を短縮するにはどうすればよいですか? または、サーバーが安全な接続をサポートしているかどうかを確認するためのより良い方法はありますか?

4

1 に答える 1

0

私は決定的な答えを出すことはできません.これに関して私が経験したいくつかの問題を拡張してください.

これを試したのはどのOSですか?

私が見つけたのは、クライアント側の接続が非同期呼び出し (コールバックを伴う BeginXxxx) によってセットアップされている場合、相互認証は Windows XP では完全に機能しますが、Windows 7 以降では機能しないということです。同期メソッドは XP から 8.1 まで正常に動作しますが、非同期メソッドは XP 以外のすべてで最も奇妙な結果をもたらします。

Windows 7 では、BeginAuthenticateAsClient で渡した証明書が反対側に届かないように見えます。SslStream コンストラクターによって設定されたリモート証明書検証コールバックは、証明書およびチェーン パラメーターに対して Null を取得し、SslPolicyErrors パラメーターに対して RemoteCertificateNotAvailable を取得します。[BeginAuthenticateAsClient + callback] の代わりに AuthenticateAsClient を使用すると、問題は解決します。

Windows 8.1 ではさらに奇妙でした: そこでまったく同じコードを実行すると、リモート側で SslStream コンストラクターによって設定されたリモート証明書認証コールバックが呼び出される前に、BeginAuthenticateAsClient へのコールバックが呼び出され、認証プロセスの完了が通知されました。であるため、サーバー アプリケーションはまだクライアント証明書を受け入れるか拒否する機会がありませんでした。

于 2015-03-23T15:20:04.077 に答える