考虑SslStream.AuthenticateAsServer方法,第二个参数clientCertificateRequired:
如果将其设置为true,则需要客户端证书。如果没有,它将引发异常。客户端证书将在属性RemoteCertificate中可用。
当设置为false时,不需要客户端证书,属性RemoteCertificate应始终为null。即使客户端提供了一个。
我想完成的工作是让客户决定是否提供证书。但是,如果他们确实提供了一个,我希望在服务器上知道它。
我尝试先将变量设置为true,如果失败,则回退以不需要证书。但是,这将导致“已通过身份验证的异常”。
try{
sslStream.AuthenticateAsServer(x509certificate, true, SslProtocols.Tls, true);
}catch(Exception ex){
sslStream.AuthenticateAsServer(x509certificate, false, SslProtocols.Tls, true);
}
最佳答案
我坚信这是文档缺陷。
实际上,参数clientCertificateRequired
将控制是否不忽略客户端证书。这表示:clientCertificateRequired = false
将忽略服务器端的任何客户端证书。不会检查证书的存在或有效性。clientCertificateRequired = true
将尊重服务器端发送的所有客户端证书。如果缺少客户端证书,则使用SslPolicyErrors.RemoteCertificateNotAvailable
调用验证回调,使用默认实现时会导致捕获到异常。
因此,在您的情况下:将clientCertificateRequired
设置为true
并实现自定义验证回调,如下所示:
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);