繁体   English   中英

C#-从.NET应用程序访问HTTPS URL(不导入服务器证书)不会引发SSL异常

[英]C# - Accessing HTTPS URL from .NET application (without importing server certificates) is not throwing SSL exception

我正在尝试在C#中实现服务器身份验证(使用.NET appln)。 我想实现以下目标:

  1. 使用连接到HTTPS URL

      String sslServerHost = "https://mail.google.com"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(sslServerHost); 
  2. 如果HTTPS请求失败,我将服务器证书添加到本地Windows证书存储中。

      X509Certificate cert = request.ServicePoint.Certificate; //convert the X509Certificate to an X509Certificate2 object by passing it into the constructor X509Certificate2 cert2 = new X509Certificate2(cert); X509Store userCaStore = new X509Store(storeName: StoreName.Root, storeLocation: StoreLocation.CurrentUser); // Code to import server certifictes to windows store. userCaStore.Open(OpenFlags.ReadOnly); userCaStore.Add(cert2); 

以下是我用于执行服务器身份验证的C#代码。

从下面的代码片段中可以明显看出,我几乎没有忽略证书验证,也没有将X509Certificate添加到本地信任存储中,但是我仍然能够建立与HTTPS URL的连接( WebRequest.create(url)request.GetResponse()不会抛出任何异常)

        String sslServerHost = "https://mail.google.com";
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(sslServerHost);
        request.AllowAutoRedirect = false;

        HttpWebResponse response = (HttpWebResponse)request.GetResponse();

      try
        {    
            Stream dataStream = response.GetResponseStream();
            StreamReader reader = new StreamReader(dataStream);
            string responseFromServer = reader.ReadToEnd();
            Debug.WriteLine(responseFromServer);
            Console.WriteLine(responseFromServer);

        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

鉴于我没有将服务器证书(X509Certificate)添加到本地Windows存储中,为什么尝试访问HTTPS URL时没有出现异常。

简而言之,如何在C#中实现或实现服务器身份验证,如果未添加服务器证书,则C#代码应引发异常。

对于Java,有一个很好的链接https://github.com/escline/InstallCert/blob/master/InstallCert.java ,该链接最恰当地描述了服务器身份验证机制,在该机制中,如果客户端尝试访问HTTPS服务器,而未访问服务器的证书,出现在Java信任库中,然后JVM引发异常。

该机制似乎不适用于.NET应用程序。 任何帮助或见识将不胜感激!

原因可能是mail.google.com已经受到信任,因为证书链会引出某些根证书,该根证书已经在您的证书存储区中(“受信任的根证书颁发机构”中)。

如果要测试失败,请按照教程使用OpenSSL之类的内容创建自己的CA和证书。 然后使用此不受信任的证书在IIS中建立一个网站。

根据Web请求,Web请求的正式文档证书可以安装在当前用户的“我的证书”存储中。 这可以解释为什么它永远不会引发错误。 您可以尝试连接到服务器,而无需将证书添加到证书存储中,看看是否抛出错误。

我发现可以解决此问题的解决方案涉及在ServicePointManager.ServerCertificateValidationCallback上设置回调

 ServicePointManager.ServerCertificateValidationCallback = 
 MyRemoteCertificateValidationCallback;

 public bool MyRemoteCertificateValidationCallback(System.Object sender, 
 X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
     bool isOk = true;
     // If there are errors in the certificate chain, look at each error to determine 
     the cause.
     if (sslPolicyErrors != SslPolicyErrors.None) {
         for(int i=0; i<chain.ChainStatus.Length; i++) {
             if(chain.ChainStatus[i].Status != 
  X509ChainStatusFlags.RevocationStatusUnknown) {
                  chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
                  chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
                  chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
                  chain.ChainPolicy.VerificationFlags = 
   X509VerificationFlags.AllFlags;
                  bool chainIsValid = chain.Build((X509Certificate2)certificate);
                  if(!chainIsValid) {
                  isOk = false;
                 }
             }
         }
     } else {
                X509Certificate2 cert3 = new X509Certificate2(certificate);
                bool verify = cert3.Verify();
                var cert1 = new X509Certificate2(certificate);
                if (cert1.NotAfter <= DateTime.Now)
                {
                    return false;
                }
            }
     return isOk;
 }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM