java - 将 RestTemplate 与 SSL 一起使用

标签 java spring spring-mvc ssl spring-boot

我在我的 Spring Boot 应用程序中使用 SSL 安全性。在调用地址时

final UriComponents uriComponents
            = uriComponentsBuilder.path("/api/v1.0/register/token/{token}").buildAndExpand(token);

    ResponseEntity<Boolean> response;

    try {
        response = restTemplate
                .exchange(uriComponents.toUri(),
                          HttpMethod.PUT,
                          entity,
                          Boolean.class);

扔掉我https://pastebin.com/A4Vb69hT仔细

I/O error on PUT request for "https://localhost:8443/api/v1.0/register/token/PBe3AzJ245W0sNyeg": java.security.cert.CertificateException: No name matching localhost found; nested exception is javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching localhost found

我在网上找的网站http://java.globinch.com/enterprise-java/security/fix-java-security-certificate-exception-no-matching-localhost-found/

    static {
    //for localhost testing only
    javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
            (hostname, sslSession) -> hostname.equals("localhost"));
    }

添加后,它收到更多错误 https://pastebin.com/kJZCqJ6K仔细

PUT 请求“https://localhost:8443/api/v1.0/register/token/EMNy7W9jJgsMWEn0z6hFOIHoB96zzSaeHWUs”时出现 I/O 错误:sun.security.validator.ValidatorException:PKIX 路径构建失败:sun .security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径;嵌套异常是 javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径

我现在该怎么办?

我有两个 SSL 文件 https://github.com/JonkiPro/REST-Web-Services/tree/master/src/main/resources/keystore

最佳答案

这个答案是某种在本地运行的 hack,尽管在实际环境中启用仍然可以使用证书。

只需在 restTemplate.exchange 之前调用 SSLContextHelper.disable()

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import javax.security.cert.X509Certificate;

import org.apache.log4j.Logger;

public class SSLContextHelper {

    private static final String KEY_STORE_TYPE="JKS";
    private static final String CLASS_NAME=SSLContextHelper.class.getName();
    private static final String TRANSPORT_SECURITY_PROTOCOL="TLS";
    private static final Logger logger=Logger.getLogger(SSLContextHelper.class);

    public static void enable(){
        String keystoreType = "JKS";
        InputStream keystoreLocation = null;
        char [] keystorePassword = null;
        char [] keyPassword = null;


        try {
              KeyStore keystore = KeyStore.getInstance(keystoreType);       
              keystore.load(keystoreLocation, keystorePassword);
              KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
              kmfactory.init(keystore, keyPassword);
              InputStream truststoreLocation = null;
              char [] truststorePassword = null;
              String truststoreType = KEY_STORE_TYPE;

              KeyStore truststore = KeyStore.getInstance(truststoreType);
              truststore.load(truststoreLocation, truststorePassword);
              TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

              KeyManager [] keymanagers = kmfactory.getKeyManagers();
            TrustManager [] trustmanagers =  tmfactory.getTrustManagers();

            SSLContext sslContext = SSLContext.getInstance(TRANSPORT_SECURITY_PROTOCOL);
            sslContext.init(keymanagers, trustmanagers, new SecureRandom());
            SSLContext.setDefault(sslContext);
        } catch (Exception e) {
            logger.error(CLASS_NAME+"Exception in SSL "+e.getMessage());
            e.printStackTrace();
        }
    }

    public static void disable() {
        try {
            SSLContext sslc = SSLContext.getInstance("TLS");
            TrustManager[] trustManagerArray = { (TrustManager) new NullX509TrustManager() };
            sslc.init(null, trustManagerArray, null);
            HttpsURLConnection.setDefaultSSLSocketFactory(sslc.getSocketFactory());
            HttpsURLConnection.setDefaultHostnameVerifier(new NullHostnameVerifier());
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    private static class NullX509TrustManager implements X509TrustManager {
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            System.out.println();
        }
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            System.out.println();
        }

    }

    private static class NullHostnameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

关于java - 将 RestTemplate 与 SSL 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46508592/

相关文章:

java - Android - 带有 TextView 自动滚动的 ScrollView

java - GWT 模块上的 LIBGDX 软键盘

Spring CGLib 和 EasyMock - 尝试重复的类定义

java - spring 核心中的 Autowiring 冲突与 xml 配置

java - 设置语言 springMVC/Thymeleaf

java - 未调用 Repaint()

java - 如何尽可能快地插入数据库(多线程程序)?

java - 使用派生的 AbstractSingleBeanDefinitionParser 或其他方法在 BeanPostProcessor 中配置类

java - Spring Autowiring byType 与 util :list

java - 如何在validation-text.properties 文件中使用通配符?