SignalR - Could not establish trust relationship for the SSL/TLS secure channel

ぃ、小莉子 提交于 2020-02-02 10:09:32

问题


I'm trying to Invoke my signalR hub method from server code and its giving me an error

Could not establish trust relationship for the SSL/TLS secure channel.

my server side code is something like this

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

In hub class I have one method, called for example SayHello(), which sending message to all users.

With http its working perfectly, but when I remove 80 port from my IIS bindings, and leave only https port, it giving me error every time, when trying to Start() hub connection. I tried many things that I found by searching, but non of these works. Does anyone else had similar problems, please help.


回答1:


Ok, I did something Like this

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

by this, I found my certificate and manually validate(actually pass through) it in a SSL conversation. I don't know how much legit is this solution, but for now it is.

UPDATE

I've changed ValidateRemoteCertificate() method:

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

by this I'm opening certificate store, finding my item from it, by passing thumbprint parameter from certificate chain (last element).




回答2:


A alternative approach for verifying a certificate is this:

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

One has to plug this into the Application_Start() of Global.asax.cs (Owin's startup will also work):

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


来源:https://stackoverflow.com/questions/44433067/signalr-could-not-establish-trust-relationship-for-the-ssl-tls-secure-channel

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!