2009-11-12 12 views
13

Sto utilizzando Spring RESTTemplate sul lato client per effettuare chiamate a un endpoint REST. Il client in questo caso è un'app di Spring e Tomcat è il contenitore di servlet.Perché non riesco a trovare il truststore per un handshake SSL?

Sto riscontrando problemi relativi alla connessione a un endpoint HTTPS. Sto ricevendo un errore che indica che non è possibile trovare un percorso valido per il truststore. Dove posso specificarlo? Questo è fatto a livello del contenitore o del livello di configurazione dell'applicazione (Spring)?

traccia stack:

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) 

risposta

10

È necessario configurare correttamente lo SSLContext che è fatto esterno al RESTTemplate. Questo dovrebbe iniziare:

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

In particolare, chiamata a questo metodo farà il trucco, in modo che tutte le chiamate HttpClient successivi non si cura di certificato SSL validità:

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

Dove scrivere che il codice? – kamaci

+3

Puoi scriverlo ovunque tu voglia, perché sta facendo una chiamata statica sulla classe SSLContext stessa. Fintanto che lo chiami nello stesso contesto del classloader e prima della prima chiamata HttpClient, dovresti essere pronto. –

+0

Solo per essere sicuri: la modifica del TrustManager di un SSLContext come descritto sopra non è un'azione persistente, giusto? Quindi deve essere fatto ogni volta che si avvia l'applicazione. – ptikobj

Problemi correlati