【问题标题】:SignalR - Could not establish trust relationship for the SSL/TLS secure channelSignalR - 无法为 SSL/TLS 安全通道建立信任关系
【发布时间】:2017-06-08 10:22:16
【问题描述】:

我正在尝试从服务器代码调用我的 signalR 集线器方法,它给了我一个错误

无法为 SSL/TLS 安全通道建立信任关系。

我的服务器端代码是这样的

private void InvokeNotification(string methodName, params object[] args)
{
    try
    {
        string serverIp = ConfigurationManager.AppSettings["ServerIp"];
        var connection = new HubConnection(serverIp, useDefaultUrl: true);

        var myHub = connection.CreateHubProxy("myhub");
        connection.Start().Wait();
        myHub.Invoke(methodName, args);
    }
    catch (Exception ex)
    {
        //Some error handling
    }
}

在集线器类中,我有一种方法,例如称为SayHello(),它向所有用户发送消息。

使用 http 它可以完美运行,但是当我从 IIS 绑定中删除 80 端口并只保留 https 端口时,每次尝试 Start() 集线器连接时都会出错。我尝试了很多通过搜索找到的东西,但这些都不起作用。 有没有其他人遇到过类似的问题,请帮忙。

【问题讨论】:

    标签: c# ssl https signalr


    【解决方案1】:

    好的,我做了这样的事情

     private void InvokeNotification(string methodName, params object[] args)
     {
         try
         {
             string serverIp = ConfigurationManager.AppSettings["ServerIp"];
             var connection = new HubConnection(serverIp, useDefaultUrl: true);
             var myHub = connection.CreateHubProxy("myhub");
    
             //This will ignore all certeficates
             //System.Net.ServicePointManager.ServerCertificateValidationCallback =
             //    ((sender, certificate, chain, sslPolicyErrors) => true);
    
             System.Net.ServicePointManager.ServerCertificateValidationCallback += 
                        new RemoteCertificateValidationCallback(ValidateRemoteCertificate);
             connection.Start().Wait();
             myHub.Invoke(methodName, args);
         }
         catch (Exception ex)
         {
             //Some error handling
         }
      }
    
    private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, 
                                        X509Chain chain, SslPolicyErrors policyErrors)
    {
        bool result = false;
        if (cert.Subject.ToUpper().Contains("MY_CERT_ISSUER_NAME"))
        {
            result = true;
        }
        return result;
    }
    

    通过这个,我找到了我的证书并在 SSL 对话中手动验证(实际上是通过)它。我不知道这个解决方案有多少合法性,但现在是合法的。

    更新

    我已更改ValidateRemoteCertificate() 方法:

    private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, 
                                        X509Chain chain, SslPolicyErrors policyErrors)
    {
        bool result = false;
        X509Certificate2 cert2 = (X509Certificate2)cert;
        X509Store store = new X509Store(StoreName.Root);
        store.Open(OpenFlags.ReadOnly);
        X509Certificate2Collection cc = store.Certificates.Find(X509FindType.FindByThumbprint, 
             chain.ChainElements[chain.ChainElements.Count - 1].Certificate.Thumbprint, true);
        store.Close();
        if (cc.Count > 0)
        {
            result = true;
        }
        return result;
    }
    

    通过这个我打开证书存储,从中找到我的项目,通过从证书链(最后一个元素)传递指纹参数。

    【讨论】:

      【解决方案2】:

      验证证书的另一种方法是:

      static internal class SSLCertificateResolverConfigurator
      {
          static internal void Setup()
          {
              ServicePointManager.ServerCertificateValidationCallback += ValidateRemoteCertificate;
          }
      
          static private bool ValidateRemoteCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) //0
          {
              if (policyErrors == SslPolicyErrors.None)
                  return true;
      
              var thumbprint = chain.ChainElements.Count > 0 ? chain.ChainElements[chain.ChainElements.Count - 1].Certificate.Thumbprint : null;
              if (thumbprint == null) //somethings wrong
                  return false;
      
              var sha1CertHashString = certificate.GetCertHashString();
              if (sha1CertHashString == null) //somethings wrong
                  return false;
      
              if (ApprovedCertificatesSHA1Cache.ContainsKey(sha1CertHashString))
                  return true;
      
              try
              {
                  var asCertificate2 = certificate as X509Certificate2 ?? new X509Certificate2(certificate);
                  X509CertificateValidator.ChainTrust.Validate(asCertificate2); //1
                  ApprovedCertificatesSHA1Cache.TryAdd(sha1CertHashString, sha1CertHashString);
                  return true;
              }
              catch
              {
                  return false;
              }
      
              //0 vital for signalr to work via https  https://stackoverflow.com/questions/44433067/signalr-could-not-establish-trust-relationship-for-the-ssl-tls-secure-channel
              //1 chaintrust checks both personal account specific certificates and the trusted root certificates authorities
          }
      
          static private readonly ConcurrentDictionary<string, string> ApprovedCertificatesSHA1Cache = new ConcurrentDictionary<string, string>();
      }
      

      必须将其插入 Global.asax.cs 的 Application_Start() 中(Owin 的启动也可以):

      public class MvcApplication : HttpApplication
      {
          protected void Application_Start()
          {
              [...]
              SSLCertificateResolverConfigurator.Setup();
          }
      }
      //  for instructions on enabling IIS6 or IIS7 classic mode visit http://go.microsoft.com/?LinkId=9394801
      

      【讨论】:

        猜你喜欢
        • 2014-07-17
        • 2011-05-28
        • 1970-01-01
        • 1970-01-01
        • 2021-12-06
        • 2016-08-30
        • 1970-01-01
        • 1970-01-01
        • 2012-03-12
        相关资源
        最近更新 更多