English 中文(简体)
How to solve "Could not establish trust relationship for the SSL/TLS secure channel with authority"
原标题:

I have a WCF service hosted in IIS 7 using HTTPS. When I browse to this site in Internet Explorer, it works like a charm, this is because I have added the certificate to the local root certificate authority store.

I m developing on 1 machine, so client and server are same machine. The certificate is self-signed directly from IIS 7 management snap in.

I continually get this error now...

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

... when called from client console.

I manually gave myself permissions and network service to the certificate, using findprivatekey and using cacls.exe.

I tried to connect to the service using SOAPUI, and that works, so it must be an issue in my client application, which is code based on what used to work with http.

Where else can I look I seem to have exhausted all possibilities as to why I can t connect?

最佳回答

As a workaround you could add a handler to the ServicePointManager s ServerCertificateValidationCallback on the client side:

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
    (se, cert, chain, sslerror) =>
        {
            return true;
        };

but be aware that this is not a good practice as it completely ignores the server certificate and tells the service point manager that whatever certificate is fine which can seriously compromise client security. You could refine this and do some custom checking (for certificate name, hash etc). at least you can circumvent problems during development when using test certificates.

问题回答

When I have this problem it is because the client.config had its endpoints like:

 https://myserver/myservice.svc 

but the certificate was expecting

 https://myserver.mydomain.com/myservice.svc

Changing the endpoints to match the FQDN of the server resolves my problem. I know this is not the only cause of this problem.

Your problem arises because you re using a self signed key. The client does not trust this key, nor does the key itself provide a chain to validate or a certificate revocation list.

You have a few options - you can

  1. turn off certificate validation on the client (bad move, man in the middle attacks abound)

  2. use makecert to create a root CA and create certificates from that (ok move, but there is still no CRL)

  3. create an internal root CA using Windows Certificate Server or other PKI solution then trust that root cert (a bit of a pain to manage)

  4. purchase an SSL certificate from one of the trusted CAs (expensive)

the first two use lambda, the third uses regular code... hope you find it helpful

            //Trust all certificates
            System.Net.ServicePointManager.ServerCertificateValidationCallback =
                ((sender, certificate, chain, sslPolicyErrors) => true);

            // trust sender
            System.Net.ServicePointManager.ServerCertificateValidationCallback
                = ((sender, cert, chain, errors) => cert.Subject.Contains("YourServerName"));

            // validate cert by calling a function
            ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);

    // callback used to validate the certificate in an SSL conversation
    private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
    {
        bool result = false;
        if (cert.Subject.ToUpper().Contains("YourServerName"))
        {
            result = true;
        }

        return result;
    }

A one line solution. Add this anywhere before calling the server on the client side:

System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate { return true; };

This should only be used for testing purposes because the client will skip SSL/TLS security checks.

If you use .net core try this:

client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
        new X509ServiceCertificateAuthentication()
        {
            CertificateValidationMode = X509CertificateValidationMode.None,
            RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
        };

I encountered the same problem and I was able to resolve it with two solutions: First, I used the MMC snap-in "Certificates" for the "Computer account" and dragged the self-signed certificate into the "Trusted Root Certification Authorities" folder. This means the local computer (the one that generated the certificate) will now trust that certificate. Secondly I noticed that the certificate was generated for some internal computer name, but the web service was being accessed using another name. This caused a mismatch when validating the certificate. We generated the certificate for computer.operations.local, but accessed the web service using https://computer.internaldomain.companydomain.com. When we switched the URL to the one used to generate the certificate we got no more errors.

Maybe just switching URLs would have worked, but by making the certificate trusted you also avoid the red screen in Internet Explorer where it tells you it doesn t trust the certificate.

Please do following steps:

  1. Open service link in IE.

  2. Click on the certificate error mention in address bar and click on View certificates.

  3. Check issued to: name.

  4. Take the issued name and replace localhost mention in service and client endpoint base address name with A fully qualified domain name (FQDN).

For Example: https://localhost:203/SampleService.svc To https://INL-126166-.groupinfra.com:203/SampleService.svc

In addition to the answers above, you could encounter this error if your client is running the wrong TLS version, for example if the server is only running TLS 1.2.

You can fix it by using:

// tested in .NET 4.5:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

I had the same problem. I also had added CA certificates in the local store, but I did in the WRONG way.

Using mmc Console (Start -> Run -> mmc ) you should add Certificates snap-in as Service account (choosing the service account of IIS) or Computer account (it adds for every account on the machine)

Here an image of what I m talking about Add snap-in for a service account or the computer account

From here now, you can add certificates of CAs (Trusted Root CAs and Intermediate CAs), and everything will work fine

I had similar issue with self-signed certificate. I could resolve it by using the certificate name same as FQDN of the server.

Ideally, SSL part should be managed at the server side. Client is not required to install any certificate for SSL. Also, some of the posts mentioned about bypassing the SSL from client code. But I totally disagree with that.

I just dragged the certificate into the "Trusted Root Certification Authorities" folder and voila everything worked nicely.

Oh. And I first added the following from a Administrator Command Prompt:

netsh http add urlacl url=https://+:8732/Servicename user=NT-MYNDIGHETINTERAKTIV

I am not sure of the name you need for the user (mine is norwegian as you can see !): user=NT-AUTHORITY/INTERACTIVE ?

You can see all existing urlacl s by issuing the command: netsh http show urlacl

I just wanted to add something to the answer of @NMrt who already pointed out:

you could encounter this error if your client is running the wrong TLS version, for example if the server is only running TLS 1.2.

With Framework 4.7.2, if you do not explicitly configure the target framework in your web.config like this

<system.web>
  <compilation targetFramework="4.7" />
  <httpRuntime targetFramework="4.7" />
</system.web>

your system default security protocols will be ignored and something "lower" might be used instead. In my case Ssl3/Tls instead of Tls13.

  • You can fix this also in code by setting the SecurityProtocol (keeps other protocols working):

    System.Net.ServicePointManager.SecurityProtocol |= System.Net.SecurityProtocolType.Tls12 | System.Net.SecurityProtocolType.Tls11;
    System.Net.ServicePointManager.SecurityProtocol &= ~System.Net.SecurityProtocolType.Ssl3;
    
  • or even by adding registry keys to enable or disable strong crypto

    [HKEY_LOCAL_MACHINESOFTWAREMicrosoft.NETFrameworkv4.0.30319]
    "SchUseStrongCrypto"=dword:00000001
    

This blog post pointed me to the right direction and explains the backgrounds better than I can:

https://www.ryadel.com/en/asp-net-client-server-cannot-comunicate-because-they-possess-common-algorithm-how-to-fix-c-sharp/

This occurred when trying to connect to the WCF Service via. the IP e.g. https://111.11.111.1:port/MyService.svc while using a certificate tied to a name e.g. mysite.com.

Switching to the https://mysite.com:port/MyService.svc resolved it.

This occurred when trying to connect to the WCF Service using only host name e.g. https://host/MyService.svc while using a certificate tied to a name e.g. host.mysite.com.

Switching to the https://host.mysite.com/MyService.svc and this resolved it.

Just fixed a similar issue.

I realized I had an application pool that was running under an account that only had reading permission over the certificate that it was used.

The .NET application could correctly retrieve the certificate but that exception was thrown only when GetRequestStream() was called.

Certificates permissions can be managed via MMC console

If you are using .net core, then during development you can bypass certificate validation by using compiler directives. This way will only validate certificate for release and not for debug:

#if (DEBUG)
        client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
                new X509ServiceCertificateAuthentication()
                {
                    CertificateValidationMode = X509CertificateValidationMode.None,
                    RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
                };   #endif

To help with troubleshooting, you can add this temporarily to log additional info about the cert that s causing the validation failure. I logged it to NLog s txt log but you can create EventLog if you want:

System.Net.ServicePointManager.ServerCertificateValidationCallback += (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) =>
{
    StringBuilder sb = new StringBuilder();
    sb.AppendLine($"  Certificate Subject: {certificate.Subject}");
    sb.AppendLine($"  Certificate Issuer: {certificate.Issuer}");
    sb.AppendLine($"  Certificate CertHash: {certificate.GetCertHashString()}");
    sb.AppendLine($"  Certificate EffectiveDate: {certificate.GetEffectiveDateString()}");
    sb.AppendLine($"  Certificate ExpirationDate: {certificate.GetExpirationDateString()}");
    sb.AppendLine($"  sslPolicyErrors: {sslPolicyErrors.ToString()}");
    sb.AppendLine($"  ChainPolicy:");
    sb.AppendLine($"     Chain revocation flag: {chain.ChainPolicy.RevocationFlag}");
    sb.AppendLine($"     Chain revocation mode: {chain.ChainPolicy.RevocationMode}");
    sb.AppendLine($"     Chain verification flag: {chain.ChainPolicy.VerificationFlags}");
    sb.AppendLine($"     Chain verification time: {chain.ChainPolicy.VerificationTime}");
    sb.AppendLine($"     Chain status length: {chain.ChainStatus.Length}");
    sb.AppendLine($"     Chain application policy count: {chain.ChainPolicy.ApplicationPolicy.Count}");
    sb.AppendLine($"     Chain certificate policy count: {chain.ChainPolicy.CertificatePolicy.Count}");

    sb.AppendLine($"  ChainStatus:");
    foreach (var cs in chain.ChainStatus)
    {
        sb.AppendLine($"     Chain certificate policy count: Status: {cs.Status}, StatusInformation: {cs.StatusInformation}");
    }

    NLog.Common.InternalLogger.Error($"ServerCertificateValidationCallback: {sb}
");

    return true;
};




相关问题
Session Management with Windows Authentication

In an ASP.NET web app, using Integrated Windows Authentication, is the session tied to the windows identity? In other words, if I login (using IWA) to the app, and the app stores some "stuff" in my ...

Using Elmah with Cassini

Does anyone know if I can use Elmah with Visual Studio build-in web server(aka Cassini)? I get it working easily on IIS, but using same configuration, it doesn t work with Cassini. When I requested ...

Setting hostname in IIS, include www?

I want to set the hostname for a website I m adding in IIS 7, however do I include the www in the hostname or not? because I want both www.mysite.com and mysite.com both to point to mysite on the ...

inetpub versus any other folder

I ve run websites out of inetpub, as well as from folders just residing on the C: drive. I wonder, are there any definitive advantages to running websites out of inetputwwwroot?

IIS 6.0 hangs when serving a web-service

I am having issues with one of our web-services. It works fine on my development machine (win XP) whether I host it as a separate application or using cassini from Visual studio. Once I deploy on the ...

热门标签