it-roy-ru.com

Ошибка SSL "Peer Not Authenticated" с HttpClient 4.1

Я создаю простой монитор приложения для опроса одного из наших URL-адресов API и отправки нам электронного письма, если он не может получить код состояния HTTP 200 из ответа (это будет означать, что наш API по какой-то причине не работает).

Я использую HttpClient 4.1 (это важно, потому что его API отличается значительно от 3.x).

Наш API защищен с помощью SSL, однако введите:

http://example.com/our-api

в веб-браузер перенаправляет вас на

https://example.com/our-api

Не вызывая ошибок.

Когда HttpClient пытается получить доступ к этому URL (http://example.com/our-api), происходит сбой с исключением javax.net.ssl.SSLPeerUnverifiedException с сообщением:

сверстник не аутентифицирован

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

То, что этот другой пост (и другие подобные ему) не делают, это объяснить, почему это происходит в первую очередь! Так что вместо того, чтобы спрашивать "как мне это исправить?" Я решил спросить «почему это происходит?» Прежде чем я начну с одним из предложенных решений, я хотел бы знать, в чем заключается проблема, которую я пытаюсь решить ;-)

20
IAmYourFaja

Если сертификат сервера самоподписан, то он работает в соответствии с планом, и вам придется импортировать сертификат сервера в хранилище ключей.

Предполагая, что сертификат сервера подписан известным CA, это происходит потому, что набор сертификатов CA, доступных для современного браузера, намного больше, чем ограниченный набор, поставляемый с JDK/JRE.

Решение EasySSL, приведенное в одном из упомянутых вами постов, просто скрывает ошибку, и вы не узнаете, есть ли у сервера действительный сертификат.

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

24
Jim Garrison

Это бросается когда 

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

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

Ответ заключается в том, чтобы извлечь корневой сертификат (например, из SSL-соединения вашего браузера), импортировать его в файл cacerts и доверить ему, используя keytool, который поставляется Java JDK. В противном случае вам придется назначить другое хранилище доверия программно.

6
Maarten Bodewes
keytool -import -v -alias cacerts -keystore cacerts.jks -storepass changeit -file C:\cacerts.cer
1
vaquar khan

Я не Java-разработчик, но использовал Java-приложение для тестирования RESTful API. Чтобы исправить ошибку, мне пришлось установить промежуточные сертификаты на веб-сервере, чтобы ошибка исчезла. Я использовал lighttpd, оригинальный сертификат был установлен на сервере IIS. Надеюсь, поможет. Это были сертификаты, которые мне не хватало на сервере. 

  • Ca.crt
  • UTNAddTrustServer_CA.crt
  • AddTrustExternalCARoot.crt
0
pabloh007