如果需要访问一个带有 ssl 的网站或 Web Service 时,需要添加一个回调函数。
using System.Net;
using System.Net.Security;
using System.Security.Cryptography;
using System.Security.Cryptogryaphy.X509Certificates;
WebServiceClient client = new WebServiceClient(); //WebServiceClient 可以通过添加 Web 服务引用的方式获取,如何添加不再熬述
ServicePointManager.ServiceCertificateValidationCallback += ValidateRemoteCertificateWhenCallback;
private static bool ValidateRemoteCertificateWhenCallback(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors)
{
bool result = false;
try
{
if (sender is WebRequest && cert is X509Certificate2 && chain != null)
{
result = errors == SslPolicyErrors.None; // 表明验证是通过的
if (!result)
{
result = chain.ChainStatus == null; // 证书生成引擎的所有元素的状态为空,证明不需要验证(这种情况实际很少出现)
if (!result)
{
result = chain.ChainStatus.Length <= 0; // 证书生成引擎的数量为 0,不需要验证(这种情况实际很少出现)
if (!result)
{
if (chain.ChainStatus.Length == 1 && chain.ChainStatus[0].Status == X509ChainStatusFlags.NoError)
result = true; // 证明 X509 链是正确的(这种情况很少出现)
else // 这是大多数的情况
{
result = ((X509Certificate2)cert).Verify(); // 使用基本验证策略执行 X509 链验证(如果客户端与服务端在同一台设备上时会可能出现这种情况)
if (!result)
// 这是大多数的情况,客户端与服务器不在同一台设备上,此时通过远程到服务端去验证证书的合法性,如果验证通过,即证明该证书是合法的
{
if (chain.ChainPolicy == null)
chain.ChainPolicy = new X509ChainPolicy();
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 30);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
chain.ChainPolicy.VerificationTime = ((X509Certificate2)cert).NotAfter;
result = chain.Build((X509Certificate2)cert); // 根据指定的策略生成 X509 链,如果能够生成,证明证书是有效的
}
}
}
}
}
}
}
catch (Exception e)
{
throw e;
}
return result;
}