双向SSL双向认证

问题描述 投票:0回答:2

我的任务是在 Spring Boot REST API 中实现功能以联系另一个 API(XML Web 服务)。外部 API 使用双向 SSL 身份验证。我已经获得了可以在我们这边实现的正确证书,并且我已经实现了 Java 代码。但每当我运行代码时,我都会收到“收到致命警报:handshake_failure”。我已将 jks 密钥库加载到 SSLContext 中,如下所示:

FileInputStream truststoreFile = new FileInputStream("/Users/myUser/Desktop/myProject/myProjectName/src/main/resources/keystore-name.jks");
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        KeyStore truststore = KeyStore.getInstance(KeyStore.getDefaultType());
        char[] trustorePassword = "keyStorePassword".toCharArray();
        truststore.load(truststoreFile, trustorePassword);
        trustManagerFactory.init(truststore);
        SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
        KeyManager[] keyManagers = {};//if you have key managers;
        sslContext.init(keyManagers, trustManagerFactory.getTrustManagers(), new SecureRandom());

我实际上是否需要配置其他任何内容才能从我们的 API 启用双向 SSL,就像我在这种情况下的客户端一样?我想我可以喜欢证书密钥库并继续。但也许我需要做其他事情才能实现这一点?

java spring ssl client-certificates
2个回答
3
投票

您在错误的上下文中使用与您共享的文件。该文件是包含客户端证书和相应密钥的密钥库。

TrustStore - 告诉客户端(您)应该信任哪些 CA。

密钥库 - 告诉服务器有关客户端(您)的信息。

为了让双向 TLS 握手通过,您需要加载 Keystore 并在 KeyManager 中进行设置,如下所示。

// Load the Keystore
KeyStore keyStore = KeyStore.getInstance("JKS");
InputStream keystoreStream = new FileInputStream(pathToJKSFile);
keyStore.load(keystoreStream, keystorePassword.toCharArray());

// Add Keystore to KeyManager
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keystorePassword.toCharArray());

// Create SSLContext with KeyManager and TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
SSLSocketFactory sslSocketFactory = context.getSocketFactory();

// Now, use this SSLSocketFactory while making the HTTPS request

0
投票

谢谢你!我遇到了完全相同的情况,编写一个 Spring Boot 应用程序,必须通过双向身份验证联系另一个 API。我对 Saravana 的代码片段进行了很少的修改,它解决了我整天被困的问题。我想我会分享我的改编,以防它对任何人有帮助。

密钥库文件(进一步声明为类属性)作为属性读入:

@Value("${externalAPI.keyStoreFile}")
private Resource keyStoreFile;

外部API为我们提供了安全通信所需的p12文件。我将文件放在资源目录中,并在 application.properties 中放入一个条目:

externalAPI.keyStoreFile=classpath:keystore/fromExternalAPI.p12

这是来自 Saravana 的改编代码片段:

        // Load the keystore
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        InputStream keyStoreStream = new FileInputStream(keyStoreFile.getFile());
        keyStore.load(keyStoreStream, keyStorePassword.toCharArray());

        // Add keystore to key manager
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());

        // Create SSLContext with KeyManager and TrustManager
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext);

        final HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create()
                .setSSLSocketFactory(sslConnectionSocketFactory)
                .build();

        CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(cm).build();
        ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);

        RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(requestFactory));
        restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(externalApiUrl));

        // Set an interceptor to log the requests and responses to/from external API
        List<ClientHttpRequestInterceptor> interceptors
                = restTemplate.getInterceptors();
        if (CollectionUtils.isEmpty(interceptors)) {
            interceptors = new ArrayList<>();
        }
        interceptors.add(new LogRequestResponseFilter());
        restTemplate.setInterceptors(interceptors);

        // Create the restClient based on the rest template
        // so we can use the new features of RestClient
        restClient = RestClient.create(restTemplate);

感谢你们分享您的知识!这是一个巨大的帮助!

© www.soinside.com 2019 - 2024. All rights reserved.