2009-11-12 27 views
13

私はクライアント側でSpring RESTTemplateを使用してRESTエンドポイントを呼び出しています。この場合のクライアントはSpringアプリケーションであり、Tomcatはサーブレットコンテナです。SSLハンドシェイクのトラストストアが見つからないのはなぜですか?

HTTPSエンドポイントへの接続に関する問題が発生しています。トラストストアへの有効なパスが見つからないことを示すエラーが表示されます。これはどこで指定できますか?これはコンテナレベルかアプリケーションの設定(春)レベルで行われますか?

スタックトレース:

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) 

答えて

10

あなたが適切にRESTTemplateに外部で行われたSSLContextを設定する必要があります。これは、あなたが始める必要があります。

後続のHttpClientの呼び出しは、SSL証明書の有効性を気にしないように具体的には、このメソッドを呼び出すと、トリックを行います
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

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

そのコードを記述するの? – kamaci

+3

SSLContextクラス自体で静的呼び出しを行っているので、好きな場所に書き込むことができます。あなたが同じクラスローダーコンテキストで、最初のHttpClientコールの前に呼び出すのであれば、あなたはうまくいくはずです。 –

+0

確かに:上記のようにSSLContextのTrustManagerを変更するのは永続的なアクションではありません。したがって、アプリケーションを起動するたびに実行する必要があります。 – ptikobj

関連する問題