问题
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