Java无法发送https请求“找不到有效的证书路径”

时间:2019-10-06 12:50:45

标签: java spring https truststore

我正在尝试通过https:https://api-sandbox.rabobank.nl/openapi/sandbox访问沙箱api,但是在发送请求时出现此错误: 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/mutual-tls 我很确定这与他们的证书不被我的PC /应用程序信任有关。但是就像我说的那样,我将他们的证书添加到我拥有的所有3个Java版本的所有3个cacert中...

2 个答案:

答案 0 :(得分:1)

我在您的日志中看到的是:

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
...

也就是说,您在trusstore中只有一个自签名证书。但是服务器正在使用:

*** 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");

of如果您需要在truststore中使用该证书,则最好采用Java随附的官方trustore,然后将您在cert.p12中拥有的证书添加到该证书中-或将服务器提供的链中的任何其他证书添加到该精简定制中信任库。 (理想情况下,根证书“ CN = DigiCert高保证EV根CA,OU = www.digicert.com,O = DigiCert Inc,C = US”,您可以在digicert或可能与andy一起提供的所有当前默认托管库中获得根证书)应用程序或操作系统。)

答案 1 :(得分:1)

api沙箱URL具有Digicert颁发的证书,该证书是有效的CA提供程序。 但是根据spring boot starter代码,您正在使用自签名证书启动服务器。因此,在CA签名的SSL证书和非CA签名的证书之间进行握手时,会出现PKIK异常。

请在春季启动启动时提供您正在使用的证书,并将其包含在java的cacert文件中。

SSL的真正本质是握手,在此他们交换加密密钥。在两个启用SSL的站点之间发生数据时,它们首先交换加密密钥,然后继续使用该加密密钥对数据进行加密。而且它们没有解密密钥(与SSH相同)。

@BasVelden基本上让JAVA信任任何自定义生成的(非CA生成的)密钥,我们执行以下操作:

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

现在,上述代码的解释是: keytool是Java提供的实用程序  :通常位置是$ 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文件是可以的,但是您不应该删除原始条目。因此,删除该条目对您有所帮助,而不是提供版本提供者的路径,而应提供所有提供者的上述路径。