Как решить ошибку javax.net.ssl. SSLHandshakeException?
я подключился к VPN для настройки API инвентаризации, чтобы получить список продуктов, и он отлично работает. Как только я получаю результат от веб-сервиса и привязываюсь к UI. А также я интегрировал PayPal с моим приложением для экспресс-проверки, когда я делаю звонок для оплаты, я сталкиваюсь с этой ошибкой. Я использую сервлет для внутреннего процесса. Может кто-нибудь сказать как исправить эту проблему?
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
6 ответов:
сначала нужно получить сертификат от сервера, к которому вы пытаетесь подключиться. Это можно сделать различными способами, например, связаться с администратором сервера и попросить его,используя openssl, чтобы загрузить его, или, поскольку это похоже на HTTP-сервер, подключитесь к нему с помощью любого браузера, просмотрите информацию о безопасности страницы и сохраните копию сертификата. (Google должен быть в состоянии сказать вам точно, что делать для вашего конкретного браузера.)
теперь если у вас есть сертификат, сохраненный в файле, вам нужно добавить его в хранилище доверия JVM. В
$JAVA_HOME/jre/lib/security/
для JREs или$JAVA_HOME/lib/security
для JDKs есть файл с именемcacerts
, который поставляется с Java и содержит публичные сертификаты известных сертификационных органов. Чтобы импортировать новый сертификат, запустите keytool от имени пользователя, имеющего разрешение на запись в cacerts:keytool -import -file <the cert file> -alias <some meaningful name> -keystore <path to cacerts file>
он, скорее всего, попросит у вас пароль. Пароль по умолчанию, поставляемый с java,
changeit
. Почти никто изменить его. После выполнения этих относительно простых шагов вы будете общаться безопасно и с уверенностью, что вы разговариваете с правильным сервером и только с правильным сервером (до тех пор, пока они не потеряют свой закрытый ключ).
сейчас я решил эту проблему таким образом,
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.OutputStream; // Create a trust manager that does not validate certificate chains like the default TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { //No need to implement. } public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { //No need to implement. } } }; // Install the all-trusting trust manager try { SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (Exception e) { System.out.println(e); }
конечно, это решение должно использоваться только в сценариях, где невозможно установить необходимые сертификаты с помощью
keytool
например, локальное тестирование с временными сертификатами.
всякий раз, когда мы пытаемся подключиться к URL-адресу,
если сервер на другом сайте работает по протоколу https и требует, чтобы мы общались через информацию, предоставленную в сертификате, то у нас есть следующий вариант:
1) попросите сертификат (загрузите сертификат), импортируйте этот сертификат в trustore. Использование Java trustore по умолчанию можно найти в \Java\jdk1.6. 0_29\jre\lib\security\cacerts, а затем, если мы повторим попытку подключения к URL-соединению будет принято.
2) в обычных бизнес-случаях мы можем подключаться к внутренним URL-адресам в организациях, и мы знаем, что они верны. В таких случаях Вы доверяете, что это правильный URL, в таких случаях выше, код может быть использован, который не будет поручать хранить сертификат для подключения к конкретному URL.
для пункта № 2 мы должны выполнить следующие шаги:
1) напишите ниже метод, который устанавливает HostnameVerifier для HttpsURLConnection, который возвращает true для всех случаев означает, что мы доверяем trustStore.
// trusting all certificate public void doTrustToCertificates() throws Exception { Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException { return; } public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException { return; } } }; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HostnameVerifier hv = new HostnameVerifier() { public boolean verify(String urlHostName, SSLSession session) { if (!urlHostName.equalsIgnoreCase(session.getPeerHost())) { System.out.println("Warning: URL host '" + urlHostName + "' is different to SSLSession host '" + session.getPeerHost() + "'."); } return true; } }; HttpsURLConnection.setDefaultHostnameVerifier(hv); }
2) Напишите ниже метод, который вызывает doTrustToCertificates перед попыткой подключения к URL
// connecting to URL public void connectToUrl(){ doTrustToCertificates();// URL url = new URL("https://www.example.com"); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); System.out.println("ResponseCode ="+conn.getResponseCode()); }
этот вызов вернет код ответа = 200 означает, что соединение успешно.
для получения более подробной информации и пример примера вы можете обратиться к URL.
Я считаю, что вы пытаетесь подключиться к чему-то с помощью SSL, но что-то предоставляет сертификат, который не проверяется корневыми центрами сертификации, такими как verisign.. По сути, по умолчанию безопасные соединения могут быть установлены только в том случае, если человек, пытающийся подключиться, знает ключи контрагентов или какой-либо другой verndor, такой как verisign, может вмешаться и сказать, что предоставляемый открытый ключ действительно прав..
все ОС доверяют горстке сертификации органы власти и более мелкие эмитенты сертификатов должны быть сертифицированы одним из крупных сертифицирующих органов, создающих цепочку сертифицирующих органов, если вы понимаете, что я имею в виду...
в любом случае, возвращаясь к делу.. У меня была аналогичная проблема при программировании Java-апплета и java-сервера ( надеюсь, когда-нибудь я напишу полный блог о том, как я получил всю безопасность для работы :) )
по сути, мне нужно было извлечь открытые ключи с сервера и сохранить их в хранилище ключей внутри моего апплета и когда я подключился к серверу, я использовал это хранилище ключей для создания фабрики доверия и этой фабрики доверия для создания ssl-соединения. Существуют также процедуры alterante, такие как добавление ключа к доверенному хосту JVM и изменение хранилища доверия по умолчанию при запуске..
Я сделал это около двух месяцев назад и не имеют исходных кодов на меня прямо сейчас.. используйте Google, и вы должны быть в состоянии решить эту проблему. Если вы не можете сообщение меня, и я могу предоставить вам соответствующий исходный код для проекта .. Не знаю, если это решает вашу проблему, поскольку вы не предоставили код, который вызывает эти исключения. Кроме того, я работал с апплетами думал, что я не могу понять, почему он не будет работать на Serverlets...
P. S Я не могу получить исходный код до выходных, так как внешний SSH отключен в моем офисе : (
SSLHandshakeException может быть решена 2 способами.
включение SSL
получить SSL (спросив исходного системного администратора, можно также быть загружены командой openssl, или любые браузеры загружает сертификаты)
добавить сертификат в хранилище доверенных сертификатов (cacerts в), расположенные по JRE / lib / security
укажите расположение хранилища доверия в аргументах виртуальной машины как "-Djavax.чистая.протокол SSL.надежное хранилище="
игнорируя SSL
для этого #2, пожалуйста, посетите мой другой ответ на другом сайте stackoverflow: как ingore SSL проверки игнорировать ошибки SSL сертификата с Java
сейчас я решил эту проблему таким образом,
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.OutputStream; // Create a trust manager that does not validate certificate chains like the default TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { //No need to implement. } public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { //No need to implement. } } }; // Install the all-trusting trust manager try { SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (Exception e) { System.out.println(e); }