Как решить javax.net.ssl.SSLHandshakeException Ошибка? - PullRequest
89 голосов
/ 12 июля 2011

Я подключился к VPN, чтобы настроить API инвентаризации для получения списка продуктов, и он работает нормально. Как только я получаю результат от веб-сервиса и привязываюсь к интерфейсу пользователя. А также я интегрировал 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 ]

130 голосов
/ 19 июля 2011

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

Теперь, когда у вас есть сертификат, сохраненный в файле, вам нужно добавить его в хранилище доверенных сертификатов вашей JVM.На $JAVA_HOME/jre/lib/security/ для JRE или $JAVA_HOME/lib/security для JDK есть файл с именем cacerts, который поставляется с Java и содержит публичные сертификаты известных сертифицирующих органов.Чтобы импортировать новый сертификат, запустите keytool от имени пользователя, имеющего разрешение на запись в cacerts:

keytool -import -file <the cert file> -alias <some meaningful name> -keystore <path to cacerts file>

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

14 голосов
/ 19 июля 2011

Теперь я решил эту проблему следующим образом,

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, например, локальное тестирование свременные сертификаты.

9 голосов
/ 20 марта 2014

Всякий раз, когда мы пытаемся подключиться к 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 .

0 голосов
/ 16 марта 2017

SSLHandshakeException можно разрешить двумя способами.

  1. Включение SSL

    • Получить SSL (по запросу исходного системного администратора, также может бытьзагруженный командой openssl, или любой браузер загружает сертификаты)

    • Добавьте сертификат в склад доверенных сертификатов (cacerts), расположенный в JRE / lib / security

    • укажите расположение хранилища доверенных сертификатов в аргументах vm как "-Djavax.net.ssl.trustStore ="

  2. Игнорирование SSL

    Для этого # 2пожалуйста, посетите мой другой ответ на другом веб-сайте stackoverflow: Как получить подтверждение SSL Игнорировать ошибки SSL-сертификата с Java

0 голосов
/ 30 ноября 2015

Теперь я решил эту проблему следующим образом,

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);
}
0 голосов
/ 14 июля 2011

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

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

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

По сути, мне нужно было извлечь открытые ключи с сервера и сохранить их в хранилище ключей внутри моего апплета, и когда я подключился к серверу, я использовал это хранилище ключей для создания фабрики доверия и этой фабрики доверия для создать соединение ssl. Существуют также альтернативные процедуры, такие как добавление ключа к доверенному хосту JVM и изменение хранилища доверенных сертификатов по умолчанию при запуске.

Я сделал это около двух месяцев назад, и сейчас у меня нет исходного кода. Используйте Google, и вы сможете решить эту проблему. Если вы не можете отправить мне сообщение, и я могу предоставить вам соответствующий исходный код для проекта. Не знаю, решит ли это вашу проблему, так как вы не предоставили код, который вызывает эти исключения. Кроме того, я работал с апплетами, думал, что не понимаю, почему он не работает на Serverlets ...

P.S Я не могу получить исходный код до выходных, так как в моем офисе отключен внешний SSH: (

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...