2009-11-12 2 views
13

Ich verwende das Spring RESTTemplate auf der Clientseite, um Aufrufe an einen REST-Endpunkt zu tätigen. Der Client ist in diesem Fall eine Spring-App und Tomcat ist der Servlet-Container.Warum kann ich den Truststore für einen SSL-Handshake nicht finden?

Ich bin in Probleme beim Herstellen einer Verbindung zu einem HTTPS-Endpunkt. Ich erhalte einen Fehler, der anzeigt, dass kein gültiger Pfad zum Truststore gefunden werden kann. Wo kann ich das angeben? Ist dies auf Containerebene oder auf der Ebene der Anwendungskonfiguration (Spring) ausgeführt?

Stapelüberwachung:

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) 

Antwort

10

Sie müssen richtig den SSL-Kontext konfigurieren, die die RESTTemplate externen erfolgt. Dies sollte Ihnen den Einstieg:

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); 
32

Insbesondere Aufruf dieser Methode wird es tun, so dass alle nachfolgenden Httpclient-Anrufe über SSL-Zertifikat Gültigkeit nicht kümmern wird:

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(); 
    } 
} 
+0

Wo diesen Code schreiben? – kamaci

+3

Sie können es überall schreiben, wo Sie möchten, weil es einen statischen Aufruf an die SSLContext-Klasse selbst macht. Solange Sie es im selben Classloader-Kontext und vor dem ersten HttpClient-Aufruf aufrufen, sollten Sie gut unterwegs sein. –

+0

Nur um sicher zu sein: Ändern des TrustManager eines SSLContext wie oben beschrieben ist keine dauerhafte Aktion, oder? Es muss also jedes Mal, wenn die Anwendung gestartet wird, ausgeführt werden. – ptikobj