0

我正在尝试通过 https 访问沙盒 api: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。应用程序.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 我很确定这与他们的证书不被信任有关通过我的电脑/应用程序。但是就像我说的那样,我将他们的证书添加到我拥有的所有 3 个 Java 版本的所有 3 个 cacerts 中......

4

2 回答 2

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

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

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

如果您需要信任库中的证书,最好采用 java 提供的官方信任库,并将您在 cert.p12 中的证书添加到其中 - 或者将服务器提供的链中的任何其他证书添加到精简的自定义信任库。(理想情况下是根证书“CN=DigiCert High Assurance EV Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US”,您可以在 digicert 或可能在所有当前的默认信任库等中获得与 andy 一起提供的应用程序或操作系统。)

于 2019-10-06T13:18:02.990 回答
1

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

请在 spring boot 启动中包含您正在使用的证书,并包含在 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 文件是可以的,但您不应该删除原始条目。因此,删除该条目对您有所帮助,而不是提供版本提供者的路径,您应该提供所有提供者的上述路径。

于 2019-10-06T13:20:12.180 回答