将RestTemplate与SSL一起使用

时间:2017-10-01 02:04:02

标签: 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

I/O error on PUT request for "https://localhost:8443/api/v1.0/register/token/EMNy7W9jJgsMWEn0z6hFOIHoB96zzSaeHWUs": sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

我现在该怎么办?

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

3 个答案:

答案 0 :(得分:2)

这个答案是在本地运行的某种黑客攻击,虽然在实际环境中启用仍然可以使用证书。

只需在SSLContextHelper.disable()

之前致电restTemplate.exchange
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;
        }
    }

答案 1 :(得分:1)

服务器证书不是有效的证书链,或者可能是自签名的。将证书作为可信证书添加到您的信任存储区(仅在您知道它是测试本地证书时才执行),然后尝试。

有关详情,请参阅http://nodsw.com/blog/leeland/2006/12/06-no-more-unable-find-valid-certification-path-requested-target

答案 2 :(得分:0)

证书与主机名不匹配,在本例中为localhost。请检查您的自签名证书是否使用了正确的CN,如果没有重新创建它。

好文章如何修复错误:

http://java.globinch.com/enterprise-java/security/fix-java-security-certificate-exception-no-matching-localhost-found/