2014-11-14 79 views
1

考慮SslStream.AuthenticateAsServer方法,第二個參數clientCertificateRequired:如果它被設置爲trueSslStream AuthenticateAsServer具有可選ClientCertificate

,需要客戶端證書。如果不是,它會拋出異常。客戶證書將在RemoteCertificate

設置爲false時,不需要客戶端證書,屬性RemoteCertificate應始終爲空。即使是由客戶提供的。

我喜歡做的是讓客戶決定是否會提供證書。但是,如果他們提供一個,我想在服務器上知道它。

我試圖首先將變量設置爲true,如果失敗,則回退到不需要certificat。但是,這會導致「已驗證的例外」。

try{ 
     sslStream.AuthenticateAsServer(x509certificate, true, SslProtocols.Tls, true); 
}catch(Exception ex){ 
     sslStream.AuthenticateAsServer(x509certificate, false, SslProtocols.Tls, true); 
} 

回答

2

我堅信這是一個文檔缺陷。

其實參數clientCertificateRequired將控制客戶端證書是否爲不會被忽略。這意味着:

clientCertificateRequired = false將忽略服務器端的任何客戶端證書。沒有證書被檢查存在和有效性。

clientCertificateRequired = true將尊重服務器端發送的任何客戶端證書。如果缺少客戶端證書,則在使用默認實現時,將使用SslPolicyErrors.RemoteCertificateNotAvailable調用驗證回調,這會導致您捕獲的異常。

所以你的情況:設置clientCertificateRequiredtrue並實施了自定義驗證回調,像這樣:

var client = server.AcceptTcpClient() 
var networkStream = client.GetStream() 

var sslStream = new SslStream(
    networkStream, 
    false, 
    (sender, certificate, chain, errors) => 
    { 
     if (errors == SslPolicyErrors.None) 
     { 
      return true; 
     } 

     if (errors == SslPolicyErrors.RemoteCertificateNotAvailable) 
     { 
      // seems to be okay for you 
      return true; 
     } 

     return false; 
    }, 
    (sender, host, certificates, certificate, issuers) => x509certificate 
); 

sslStream.AuthenticateAsServer(x509certificate, true, SslProtocols.Tls, true); 
+0

我想補充。在TLS/SSL中,如果服務器希望客戶端提供證書,則服務器必須詢問客戶端。如果服務器沒有請求客戶端證書,則客戶端無法提供客戶端證書。設置'AuthenticateAsServer(clientCertificateRequired = true)'會導致服務器請求客戶端證書。還要注意,服務器端'ValidateRemoteCertificate'可以被調用,而不管'clientCertificateRequired'的設置如何,所以檢查'SslPolicyErrors.RemoteCertificateNotAvailable'並確定服務器是否可以接受是正確的方法。 – Trevor 2018-01-30 12:01:42