Java-клиент REST возвращает handshake_failure при вызове https - PullRequest
0 голосов
/ 02 мая 2018

Я пытаюсь вызвать веб-сервис HTTPS, это код, который я использую, эта функция развернута на экземпляре AWS с ОС amazon linux

public static <T> T postSecureJsonRequest(String url, Object request, Type responseType) throws Exception {

    BufferedReader br;
    HttpsURLConnection con = null;

    try {
        URL obj = new URL(null, url, new sun.net.www.protocol.https.Handler());

        con = (HttpsURLConnection) obj.openConnection();

        con.setReadTimeout(IntegrationConfiguration.getConnectionTimeOut());
        con.setRequestMethod("POST");
        con.setRequestProperty("Content-Type", "application/json");
        con.setRequestProperty("Accept", "application/json");

        con.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        if (request.getClass().equals(String.class)) {
            wr.writeBytes(request + "");

        } else {
            wr.writeBytes(gson.toJson(request));
        }

        wr.flush();
        wr.close();

        if (con.getResponseCode() != 200) {
            throw new Exception(IntegrationConstants.TECHNICAL_ERROR + " "
                    + ("failed : HTTP error code : " + con.getResponseCode() + " from the main server : " + url));
        }

        br = new BufferedReader(new InputStreamReader((con.getInputStream())));
        String inputLine;
        StringBuffer outputResponse = new StringBuffer();

        while ((inputLine = br.readLine()) != null) {
            outputResponse.append(inputLine);
        }

        return (T) gson.fromJson(outputResponse.toString(), responseType);

    } catch (Exception e) {
        throw e;
    } finally {
        if (con != null) {
            con.disconnect();
        }
    }
}

проблема в том, что функция всегда выдает Exception

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1989)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1096)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1342)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1369)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1353)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1157)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:259)
at com.wsg.bit.casino.integration.util.IntegrationUtility.postSecureJsonRequest(IntegrationUtility.java:524)

что мне здесь не хватает?

РЕДАКТИРОВАТЬ: я получил эту информацию с сервера

* TCP_NODELAY set
* Connected to api..... (1xx.2xx.1xx.1xx) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* ALPN, server accepted to use http/1.1
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
*   subject: CN=api.....
*   start date: Apr 27 09:29:11 2018 GMT
*   expire date: Jul 26 09:29:11 2018 GMT
*   common name: api.server1.ih.testenv.io
*   issuer: CN=Let's Encrypt Authority X3,O=Let's Encrypt,C=US
> GET / HTTP/1.1
> Host: api.server1.ih.testenv.io
> User-Agent: curl/7.53.1
> Accept: */*
> 
< HTTP/1.1 404 Not Found
< Server: nginx/1.10.3 (Ubuntu)
< Date: Thu, 03 May 2018 08:43:05 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 39
< Connection: keep-alive
< cache-control: max-age=0, private, must-revalidate
< x-request-id: 2klhbq0t5ahtlndlmc0003k2

Редактировать: когда я вызываю службу HTTPS из другого REST клиента, например postman, он работает нормально

1 Ответ

0 голосов
/ 02 мая 2018

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

См. Ссылки ниже для их импорта:

Как узнать, какое хранилище ключей использует моя JVM?

Как импортировать сертификат .cer в хранилище ключей Java?

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

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

    javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() {

        public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
            return hostname.equals("www.domainname.com");
        }
    }); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...