Как решить «Не удалось установить доверительные отношения для безопасного канала SSL / TLS с полномочиями»

135

Действительно думал, что я исправил эту проблему, но это было только замаскировано раньше.

У меня есть служба WCF, размещенная в IIS 7 с использованием HTTPS. Когда я просматриваю этот сайт в Internet Explorer, он работает как шарм, это потому , что я бы добавил сертификат на локальное корневое хранилище сертификатов полномочий.

Я занимаюсь разработкой на 1 машине, поэтому клиент и сервер - это одна машина. Сертификат подписывается непосредственно из оснастки управления IIS 7.

Я постоянно получаю эту ошибку сейчас ...

Не удалось установить доверительные отношения для безопасного канала SSL / TLS с полномочиями.

... при вызове из клиентской консоли.

Я вручную дал разрешения и сетевой сервис на сертификат, используя findprivatekeyи используя cacls.exe.

Я попытался подключиться к службе с помощью SOAPUI, и это работает, поэтому это должно быть проблемой в моем клиентском приложении, код которого основан на том, что раньше использовалось для работы с http.

Куда еще я могу посмотреть, я, кажется, исчерпал все возможности, почему я не могу подключиться?

JL.
источник
Если у вас есть контроль над созданием сертификатов, не забудьте про «Альтернативное имя субъекта». Как будто вы можете вставить шаблон в "* .full.domainname.com". См. Digicert.com/subject-alternative-name.htm
granadaCoder

Ответы:

198

В качестве обходного пути вы можете добавить обработчик к ServicePointManager's' ServerCertificateValidationCallbackна стороне клиента:

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

но имейте в виду, что это не очень хорошая практика, поскольку он полностью игнорирует сертификат сервера и сообщает менеджеру точки обслуживания, что любой сертификат в порядке, который может серьезно подорвать безопасность клиента. Вы можете уточнить это и сделать некоторую пользовательскую проверку (для имени сертификата, хэша и т. Д.). по крайней мере, вы можете обойти проблемы во время разработки при использовании тестовых сертификатов.

Йоахим Кершбаумер
источник
9
Я думаю, что большинство общедоступных установок будут использовать купленный сертификат, но во время разработки dev используйте вышеуказанный код в условных операторах #if. Корпоративные разработчики должны обычно устанавливать
Люк Пуплетт
2
Помог мне выяснить, как заставить мой вызов SSL WCF работать с Fiddler2 для отладки.
Роджер Уиллкокс
2
@karank Попробуйте добавить его в метод Application_Start в Global.asax (см. stackoverflow.com/a/12507094/1175419 ). Я настоятельно рекомендую использовать директиву компилятора DEIBUG #if или что-то подобное, как упомянуто в комментарии Люка.
Rich C
4
Потрясающие! Вы можете использовать лямбда-выражение как System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => true;
Dhanuka777
Небольшое дополнительное объяснение можно найти здесь: blog.effectivemessaging.com/2015_09_01_archive.html
granadaCoder
40

Когда у меня возникает эта проблема, это потому, что client.config имеет свои конечные точки, такие как:

 https://myserver/myservice.svc 

но сертификат ожидал

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

Изменение конечных точек в соответствии с полным доменным именем сервера решает мою проблему. Я знаю, что это не единственная причина этой проблемы.

Майк Чил
источник
У меня просто снова возникла эта проблема, и на этот раз она была связана с использованием неверного сертификата. Кажется, что в обоих случаях это связано с сопоставлением имен должным образом.
Майк Чил
3
В моей автоматически сгенерированной конфигурации <endpoint address = " localhost / myservice.svc ", изменив это значение на <endpoint address = " mymachine.mydoman.com/myservice.svc ", решил эту проблему .
рыцарский заряд
Это была моя проблема, и мне потребовалось два дня, чтобы найти ваш ответ. +1, я бы дал тебе +1000, если бы мог.
AussieJoe
20

первые два используют лямбду, третий использует обычный код ... надеюсь, вы найдете его полезным

            //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;
    }
Себастьян Кастальди
источник
1
// Доверяем всем сертификатам System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => {return true; }; // доверять отправителю System.Net.ServicePointManager.ServerCertificateValidationCallback + = (se, cert, chain, sslerror) => {return cert.Subject.Contains ("ca-l-9wfvrm1.ceridian.ca"); };
VoodooChild
1
Любой взломщик может подделать сертификат, пройдя все вышеперечисленные тесты. Это небезопасно.
Бьяртур Торлаций
19

Ваша проблема возникает из-за того, что вы используете самозаверяющий ключ. Клиент не доверяет этому ключу и сам ключ не предоставляет цепочку для проверки или список отзыва сертификатов.

У вас есть несколько вариантов - вы можете

  1. отключить проверку сертификата на клиенте (плохой ход, человек в середине атаки в изобилии)

  2. используйте makecert для создания корневого ЦС и создания сертификатов из этого (хорошо, переместите, но CRL по-прежнему отсутствует)

  3. создайте внутренний корневой центр сертификации, используя Windows Certificate Server или другое решение PKI, а затем доверяйте этому корневому сертификату (немного труднее управлять)

  4. приобрести сертификат SSL в одном из доверенных центров сертификации (дорого)

blowdart
источник
3
Что касается (4), StartSSL фактически даст вам бесплатный сертификат класса 1, который работает во всех основных браузерах. Они отлично работают для меня с полдюжины сайтов с низкой пропускной способностью.
moodboom
Я думаю, что № 2 в этом списке ... этот URL может помочь: blogs.technet.microsoft.com/jhoward/2005/02/02/… "Как использовать MakeCert для доверенного корневого центра сертификации и выдачи SSL-сертификатов"
granadaCoder
1
Примечание: StartCom больше не заслуживает доверия - и только что был удален из Chrome en.wikipedia.org/wiki/StartCom
Simon_Weaver
16

Решение в одну строку. Добавьте это в любом месте перед вызовом сервера на стороне клиента:

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

Это следует использовать только в целях тестирования, поскольку клиент будет пропускать проверки безопасности SSL / TLS.

Gaspa79
источник
2
Блестящий обходной путь для тестирования. Мы используем услугу, поставщик которой превратил безопасность в настоящий ад с запутанной цепочкой сертификатов безопасности, и до тех пор, пока мы не сможем заставить их сертификаты и цепочки работать должным образом, этот обходной путь - единственное, что позволяет нам продолжать разработку.
markaaronky
12

Я столкнулся с той же проблемой и смог решить ее двумя способами: во-первых, я использовал оснастку MMC «Сертификаты» для «Учетной записи компьютера» и перетащил самоподписанный сертификат в папку «Доверенные корневые центры сертификации». , Это означает, что локальный компьютер (тот, который сгенерировал сертификат) теперь будет доверять этому сертификату. Во-вторых, я заметил, что сертификат был создан для некоторого внутреннего имени компьютера, но доступ к веб-службе осуществлялся с использованием другого имени. Это вызвало несоответствие при проверке сертификата. Мы создали сертификат для computer.operations.local, но получили доступ к веб-службе с помощью https://computer.internaldomain.companydomain.com . Когда мы переключили URL-адрес на тот, который использовался для создания сертификата, у нас больше не было ошибок.

Возможно, сработало бы просто переключение URL-адресов, но, сделав сертификат доверенным, вы также избегаете красного экрана в Internet Explorer, где он говорит, что не доверяет сертификату.

Йерун-Барт Энгелен
источник
11

Если вы используете ядро ​​.net, попробуйте это:

client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
        new X509ServiceCertificateAuthentication()
        {
            CertificateValidationMode = X509CertificateValidationMode.None,
            RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
        };
Grzegorz J
источник
1
Спасибо, это работает. Но это не имеет ничего общего с ядром .net. Это универсальный рецепт :)
Александр
7

Пожалуйста, сделайте следующие шаги:

  1. Открыть сервисную ссылку в IE.

  2. Нажмите на ссылку об ошибке сертификата в адресной строке и нажмите Просмотр сертификатов.

  3. Чек выдан на: имя.

  4. Возьмите выданное имя и замените упоминание localhost в имени базового адреса конечной точки службы и клиента на Полное доменное имя (FQDN).

Например: https: // localhost : 203 / SampleService.svc To https: // INL-126166-.groupinfra.com : 203 / SampleService.svc

Рахул Рай
источник
Отлично, спасибо за этот ответ! Решил проблемы без внесения каких-либо изменений в код.
Випин Дубей
6

В дополнение к ответам выше, вы можете столкнуться с этой ошибкой, если ваш клиент работает с неверной версией TLS, например, если на сервере работает только TLS 1.2.

Вы можете исправить это с помощью:

// tested in .NET 4.5:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
NMrt
источник
в моем случае принятый ответ мне не помог, но этот сделал свое дело
Сергей
Это единственный ответ, который исправил ошибку в моем случае.
Толга
5

У меня такая же проблема. Я также добавил сертификаты CA в локальное хранилище, но сделал это НЕПРАВИЛЬНО.

С помощью консоли MMC (Пуск -> Выполнить -> MMC ) вы должны добавить сертификаты оснастку « в качестве учетной записи службы (выбирая учетную запись службы IIS) или учетной записи компьютера (она добавляется для каждой учетной записи на компьютере).

Вот изображение того, о чем я говорю Добавить оснастку для учетной записи службы или учетной записи компьютера

Теперь вы можете добавлять сертификаты CA ( Trusted Root CA и Intermediate CA ), и все будет работать нормально

dar0x
источник
4

У меня была похожая проблема с самозаверяющим сертификатом. Я мог бы решить это, используя имя сертификата, такое же, как полное доменное имя сервера.

В идеале часть SSL должна управляться на стороне сервера. Клиенту не требуется устанавливать какой-либо сертификат для SSL. Также в некоторых постах упоминается об обходе SSL из клиентского кода. Но я совершенно не согласен с этим.

Умеш Бхавсар
источник
3

Я просто перетащил сертификат в папку «Trusted Root Certification Authorities» и вуаля, все работало хорошо.

Ой. И я сначала добавил следующее из командной строки администратора:

netsh http add urlacl url=https://+:8732/Servicename user=NT-MYNDIGHET\INTERAKTIV

Я не уверен в названии, которое вам нужно для пользователя (мое, как вы видите, норвежское!): user=NT-AUTHORITY/INTERACTIVE :?

Вы можете увидеть все существующие urlacl, выполнив команду: netsh http show urlacl

Haguna
источник
0

Это произошло при попытке подключиться к службе WCF через. IP напримерhttps://111.11.111.1:port/MyService.svc при использовании сертификата, привязанного к имени, например, mysite.com.

Переключение на https://mysite.com:port/MyService.svcрешенное это.

лько
источник
0

Это произошло при попытке подключиться к службе WCF с использованием только имени хоста, например https: //host/MyService.svc, при использовании сертификата, привязанного к имени, например host.mysite.com.

Переключение на https://host.mysite.com/MyService.svc и это решило его.

Sonia
источник
0

Просто исправлена ​​похожая проблема.

Я понял, что у меня есть пул приложений, который работал под учетной записью, которая имела разрешение на чтение только того сертификата, который он использовал.

Приложение .NET может корректно получить сертификат, но это исключение выдается только при вызове GetRequestStream ().

Разрешениями на сертификаты можно управлять через консоль MMC

Alberto
источник
0

Если вы используете ядро ​​.net, то во время разработки вы можете обойти проверку сертификата с помощью директив компилятора. Этот способ будет проверять только сертификат для выпуска, а не для отладки:

#if (DEBUG)
        client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
                new X509ServiceCertificateAuthentication()
                {
                    CertificateValidationMode = X509CertificateValidationMode.None,
                    RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
                };   #endif
Панайотис Хирипис
источник
-6

Добавьте это к своему клиентскому коду:

ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(
    delegate
    {
        return true;
    });
user662285
источник
4
Этот ответ не очень хорош, поскольку он не объясняет риски, связанные с кодом.
daveD