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

时间:2017-06-08 10:22:17

标签: c# ssl https signalr

我试图从服务器代码调用我的signalR hub方法并且它给我一个错误

  

无法为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()集线器连接时都会给我错误。我尝试了许多通过搜索找到的东西,但没有这些东西。 有没有其他人有类似的问题,请帮助。

2 个答案:

答案 0 :(得分:2)

好的,我做了像这样的事情

 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;
}

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

答案 1 :(得分:1)

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

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