Java не может отправить https запрос "невозможно найти правильный путь сертификации" - PullRequest
0 голосов
/ 06 октября 2019

Я пытаюсь получить доступ к API песочницы через https: https://api -sandbox.rabobank.nl / openapi / sandbox , но я получаю эту ошибку при отправке запроса: https://pastebin.com/5X4h3wsu

Я попытался добавить сертификат из вышеупомянутого URL в доверенные хранилища jre11, jdk8, jdk7 и попытался переключить свой проект jdk / jre на эти версии. ошибка не меняется однако. Я также попытался установить это как параметры VM: -Dcom.sun.net.ssl.checkRevocation=false также не повезло. когда я включаю: -Djavax.net.debug=ssl (с java 8, опция не работает с 11), я получаю этот вывод на консоль: https://pastebin.com/5L7Lei8J

И вот весь мой код, это не так много, потому что это приложение предназначалосьпротестировать API с минимальным рабочим примером. Application.java:

package com.thebooks;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.security.KeyStore;

@SpringBootApplication
public class Application {

    static {
        System.setProperty("jdk.tls.client.protocols", "TLSv1.2");
        System.setProperty("https.protocols", "TLSv1.2");
        System.setProperty("javax.net.ssl.trustStore", System.getProperty("user.dir") + "/key/cert.p12");
        System.setProperty("javax.net.ssl.trustStorePassword", "secret");
        System.setProperty("javax.net.ssl.keyStore",  System.getProperty("user.dir") + "/key/key.p12");
        System.setProperty("javax.net.ssl.keyStorePassword", "secret");

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

                    public boolean verify(String hostname,
                                          javax.net.ssl.SSLSession sslSession) {
                        // TODO: CODE TO VERIFY Host
                        return true;
                    }
                });
    }

    @Bean
    public RestTemplate template() throws Exception {
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

HttpClient.java:

package com.thebooks.httpclient;

import com.thebooks.enums.EScope;
import com.thebooks.providers.PropertyProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class HttpClient implements CommandLineRunner {
    private String apiUrl = "https://api-sandbox.rabobank.nl/openapi/sandbox/";

    private final RestTemplate template;
    private PropertyProvider propProvider = new PropertyProvider();
    private final String CLIENT_ID = propProvider.get("client.id");

    public HttpClient(RestTemplate template) {
        this.template = template;
    }

    @Override
    public void run(String... args) throws Exception {
        ResponseEntity<Object> response = template.getForEntity(
                apiUrl + "oauth2/authorize?client_id=" + CLIENT_ID +
                        "&response_type=code&scope=" + EScope.AIS_BALANCES_READ.getValue(),
                Object.class);
        System.out.println(response.getStatusCode());
        System.out.println(response.getBody());
        System.out.println(response.getHeaders());
    }
}

Я получил большую часть этого кода с этого веб-сайта, которому принадлежит API, который я пытаюсь использовать: https://developer -sandbox.rabobank.nl /verse-tls Я почти уверен, что это связано с тем, что мой компьютер / приложение не доверяет их сертификату. Но, как я уже сказал, я добавил их сертификат ко всем 3 каскадам всех трех версий Java, которые у меня есть ...

Ответы [ 2 ]

1 голос
/ 06 октября 2019

В URL песочницы API есть сертификаты, выданные Digicert, который является действующим поставщиком CA. Но в соответствии с начальным кодом начальной загрузки вы запускаете сервер с самозаверяющим сертификатом. В результате возникает исключение PKIK, когда выполняется рукопожатие между SSL-сертификатом, подписанным CA, и сертификатом, не подписанным CA.

Пожалуйста, включите сертификат, который вы используете в начале весенней загрузки, и включите его вcacert файл java.

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

@ BasVelden в основном для того, чтобы JAVA доверял любому сгенерированному (не сгенерированному без ключа) ключу, мы делаем следующее:

keytool -import -trustcacerts -noprompt -keystore <full path to cacerts> -storepass changeit -alias $REMHOST -file $REMHOST.pem

Теперь пояснение к приведенному выше коду: keytool - это утилита, предоставляемая java: normall расположение: $ JAVA_HOME / jre / lib / security / cacerts. И он имеет запись всех проверенных (CA) поставщиков сертификатов. Вы изменяете эту запись

System.setProperty("javax.net.ssl.trustStore", System.getProperty("user.dir") + "/key/cert.p12");
        System.setProperty("javax.net.ssl.trustStorePassword", "secret");

Изменение файла cacerts в порядке, но вы не должны удалять исходные записи. Таким образом, удаление этой записи помогло вам, вместо того, чтобы указывать путь к поставщику версий, вы должны указать вышеуказанный путь для всех поставщиков.

1 голос
/ 06 октября 2019

То, что я вижу в ваших журналах:

trustStore is: C:\Projects\Java\rabobank-test\key\cert.p12
trustStore type is : jks
trustStore provider is :
init truststore
adding as trusted cert:
  Subject: CN=BAS, O=Internet Widgits Pty Ltd, L=rotterdam, ST=Zuid-Holland, C=NL
  Issuer:  CN=BAS, O=Internet Widgits Pty Ltd, L=rotterdam, ST=Zuid-Holland, C=NL
  Algorithm: RSA; Serial number: 0x28038baf12a3bb7ac23561ced39bccfcd39f4320
  Valid from Sat Oct 05 01:53:40 CEST 2019 until Sun Oct 04 01:53:40 CEST 2020

 keyStore is : C:\Projects\Java\rabobank-test/key/key.p12
...

То есть у вас был только один самозаверяющий сертификат в хранилище доверенных сертификатов. Но сервер использует:

*** Certificate chain
chain [0] = [
[
  Version: V3
  Subject: CN=api-sandbox.rabobank.nl, OU=IT Infrastructure, O=Cooperatieve Rabobank U.A., L=Utrecht, ST=Utrecht, C=NL
  Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

  Key:  Sun RSA public key, 2048 bits
  modulus: 27656546023135416343313786390568312089793225750931433930372419682926699102088570108432798752674580685572610333594008304037355692016847885153850390570343526804649453871166596416120002483261389717541107277089107192149483397960566607102497541257381555870488778889499740452903944947628925771418610305207680346062007754393210604748206767028477705328447039960783496889675884109837662283459562174450768283022227873621702545924115688805804041495718666206232889227995689049914624465380330588827667219738388577693826776185042246003908945385397658276988973592052614956050490934357249690728764920020238886239735311604792591584317
  public exponent: 65537
  Validity: [From: Mon Aug 05 02:00:00 CEST 2019,
               To: Mon Aug 09 14:00:00 CEST 2021]
  Issuer: CN=DigiCert SHA2 High Assurance Server CA, OU=www.digicert.com, O=DigiCert Inc, C=US
  SerialNumber: [    05d8fed0 ed99a7c7 20081752 711f1798]
...
chain [1] = [
[
  Version: V3
  Subject: CN=DigiCert SHA2 High Assurance Server CA, OU=www.digicert.com, O=DigiCert Inc, C=US
  Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

  Key:  Sun RSA public key, 2048 bits
  modulus: 23085922014910748503624791917480115148492919026914207610707020942093828159221184419960399297678177590153378092714640886296044490661625022319263060388275515964365478738040978664516396912933675650257207760237777280773935047177225664304566903694731631728916260237117586511459590661362255543750987738241463266555577715629664656907640120826399947323444556799362651693283202076722872218490347588587929811327918605576169523712767591239193274840826201053308722900104999956283622772648025895714833602740679819670062830777938157004975732087864164660384513848296643542134747514357423990884765641067184766081973460304136714018531
  public exponent: 65537
  Validity: [From: Tue Oct 22 14:00:00 CEST 2013,
               To: Sun Oct 22 14:00:00 CEST 2028]
  Issuer: CN=DigiCert High Assurance EV Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US
  SerialNumber: [    04e1e7a4 dc5cf2f3 6dc02b42 b85d159f]
...

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

Так что просто отключите линии

        System.setProperty("javax.net.ssl.trustStore", System.getProperty("user.dir") + "/key/cert.p12");
        System.setProperty("javax.net.ssl.trustStorePassword", "secret");

из, если вам нужен этот сертификат в хранилище доверенных сертификатов, оптимально взять официальный trustore, поставляемый с java, и добавить к нему сертификат, который есть в yout cert.p12, или добавить любые другие сертификаты из цепочки, к которой сервер предлагаетчто разделили таможенное хранилище. (В идеале это корневой сертификат «CN = DigiCert High Assurance EV Root CA, OU = www.digicert.com, O = DigiCert Inc, C = US», который вы получаете в digicert или, возможно, во всех текущих доверенных пользователях по умолчанию и т.п., поставляемых с andyприложение или операционная система.)

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