【问题标题】:Why can't I find the truststore for an SSL handshake?为什么我找不到 SSL 握手的信任库?
【发布时间】:2010-12-16 02:25:09
【问题描述】:

我在客户端使用 Spring RESTTemplate 来调用 REST 端点。在这种情况下,客户端是 Spring 应用程序,而 Tomcat 是 servlet 容器。

我在连接 HTTPS 端点时遇到问题。我收到一个错误,表明它找不到信任库的有效路径。我在哪里可以指定这个?这是在容器级别还是应用程序配置(Spring)级别完成的?

堆栈跟踪:

org.springframework.web.client.ResourceAccessException: I/O error:
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
org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:330)
org.springframework.web.client.RestTemplate.execute(RestTemplate.java:292)
org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:227)

【问题讨论】:

    标签: java spring tomcat rest ssl


    【解决方案1】:

    更具体地说,调用此方法可以解决问题,因此任何后续的 HttpClient 调用都不会关心 SSL 证书的有效性:

    public static void trustSelfSignedSSL() {
        try {
            SSLContext ctx = SSLContext.getInstance("TLS");
            X509TrustManager tm = new X509TrustManager() {
    
                public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
                }
    
                public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
                }
    
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };
            ctx.init(null, new TrustManager[]{tm}, null);
            SSLContext.setDefault(ctx);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    

    【讨论】:

    • 你可以在任何你喜欢的地方写它,因为它对 SSLContext 类本身进行静态调用。只要你在同一个类加载器上下文中调用它,并且在第一次 HttpClient 调用之前,你就可以开始了。
    • 只是为了确定:如上所述更改 SSLContext 的 TrustManager 不是持久操作,对吗?所以每次启动应用都需要做。
    • 作为参考,我必须导入以下内容才能使用它... import javax.net.ssl.SSLContext;导入 javax.net.ssl.X509TrustManager;导入 java.security.cert.X509Certificate;导入 javax.net.ssl.TrustManager;导入 java.security.cert.CertificateException;
    【解决方案2】:

    您需要正确配置在 RESTTemplate 外部完成的 SSLContext。这应该可以帮助您开始:

        String keystoreType = "JKS";
        InputStream keystoreLocation = null;
        char [] keystorePassword = null;
        char [] keyPassword = null;
    
        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 = "JKS";
    
        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("TLS");
        sslContext.init(keymanagers, trustmanagers, new SecureRandom());
        SSLContext.setDefault(sslContext);
    

    【讨论】:

      猜你喜欢
      • 2012-03-04
      • 2014-06-27
      • 2012-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      • 1970-01-01
      • 2016-04-01
      相关资源
      最近更新 更多