2009-11-12 4 views
13

저는 REST 엔드 포인트를 호출하기 위해 클라이언트 측에서 Spring RESTTemplate을 사용하고 있습니다. 이 경우 클라이언트는 Spring 애플리케이션이고 Tomcat은 서블릿 컨테이너입니다.SSL 핸드 셰이크의 트러스트 스토어를 찾을 수없는 이유는 무엇입니까?

HTTPS 끝점에 연결하는 데 문제가 있습니다. 트러스트 스토어에 대한 유효한 경로를 찾을 수 없음을 나타내는 오류가 표시됩니다. 이것을 어디에서 지정할 수 있습니까? 이 작업은 컨테이너 레벨 또는 응용 프로그램 구성 (스프링) 레벨에서 수행됩니까?

스택 추적 : 당신은 제대로 RESTTemplate 외부 이루어집니다의 SSLContext를 구성해야

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

. 이것은 당신이 시작할 수 있어야합니다

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

보다 구체적으로, 이후 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(); 
    } 
} 
+0

어디 그 코드를 작성? – kamaci

+3

SSLContext 클래스 자체에서 정적 호출을하기 때문에 원하는 위치에 쓸 수 있습니다. 같은 클래스 로더 컨텍스트에서 호출하고 HttpClient 콜을 호출하기 전에는 좋은 결과를 얻으실 수 있습니다. –

+0

확실한 것은 위에서 설명한대로 SSLContext의 TrustManager를 변경하는 것이 지속적인 작업이 아니라는 것입니다. 따라서 응용 프로그램이 시작될 때마다 수행해야합니다. – ptikobj

관련 문제