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

时间:2018-06-14 15:43:13

标签: c# .net ssl ssl-certificate x509certificate

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

  1. 使用

    连接到HTTPS网址
        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);
    
  3. 以下是我用于执行服务器身份验证的C#代码。

    从下面的代码片段可以看出,我没有忽略证书验证NOR将X509Certificate添加到本地信任库,但我仍然能够建立与HTTPS URL的连接(WebRequest.create(url)和{{1不抛出任何异常)

    request.GetResponse()

    为什么我在尝试访问HTTPS URL时没有出现异常,因为我没有将服务器证书(X509Certificate)添加到本地Windows应用商店。

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

    对于Java,有一个很好的链接https://github.com/escline/InstallCert/blob/master/InstallCert.java,它最好地描述了服务器身份验证机制,如果客户端尝试访问HTTPS服务器,并且如果Java信任存储中不存在服务器证书,则JVM会抛出例外。

    这种机制似乎不适合.NET应用程序。任何帮助或见解将不胜感激!!

3 个答案:

答案 0 :(得分:0)

原因可能是mail.google.com已经被信任,因为证书链导致了一些已经存在于证书库中的根证书(在#34;受信任的根证书颁发机构")。 / p>

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

答案 1 :(得分:0)

根据Web请求official documentation of the web request证书可以安装在当前用户的My certificate store中。这可能解释了为什么它会引发错误。您可以尝试连接到服务器,而无需将证书添加到证书库,并查看是否发生了错误。

答案 2 :(得分:0)

我找到解决此问题的解决方案涉及在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;
 }