2017-12-15 53 views
0

この問題について多くのことを読んでいますが、最も単純な回避策(最後のコード例はhttp://www.baeldung.com/httpclient-ssl)が見つかりましたが、仕事。ここでSpring RestTemplateを使用してHTTPS Rest APIを使用してホスト検証をバイパスする

は、私は、ホスト名の検証と私のRestTemplateがオフ(およびプロキシ設定)を宣言する方法である:

@Bean 
    public RestTemplate restTemplate(RestTemplateBuilder builder) { 

    CloseableHttpClient httpClient = HttpClients.custom() 
     .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) 
     .setProxy(new HttpHost("10.xx.xx.xx", 3128, "http")) 
     .build(); 
    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); 
    requestFactory.setHttpClient(httpClient); 
    return builder.requestFactory(requestFactory).build(); 

    //return builder.build(); 
    } 

そして、ここでは私のPOSTリクエストを作成するためのコードは次のとおりです。

LoginResponse loginResponse = restTemplate.postForObject("https://interflex.svc.suezsmartsolutions.com/path/to/my/api", loginRequest, LoginResponse.class); 

そして、ここに(ホスト名検証者を無効にしていない場合と同じように)例外です:

16:15:27 ERROR org.springframework.boot.SpringApplication:771 - Application startup failed 
java.lang.IllegalStateException: Failed to execute CommandLineRunner 
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:735) 
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:716) 
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:703) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:304) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) 
    at hello.Application.main(Application.java:23) 
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://interflex.svc.suezsmartsolutions.com/path/to/api": 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 
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:673) 
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:620) 
    at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:387) 
    at hello.Application.lambda$0(Application.java:45) 
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:732) 
    ... 6 common frames omitted 
Caused by: 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 
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) 
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949) 
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302) 
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296) 
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1514) 
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216) 
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026) 
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:961) 
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062) 
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) 
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403) 
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387) 
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:396) 
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.upgrade(DefaultHttpClientConnectionOperator.java:193) 
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.upgrade(PoolingHttpClientConnectionManager.java:375) 
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:416) 
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237) 
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185) 
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) 
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111) 
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) 
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83) 
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56) 
    at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:89) 
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) 
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) 
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:659) 
    ... 10 common frames omitted 
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387) 
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) 
    at sun.security.validator.Validator.validate(Validator.java:260) 
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) 
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229) 
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) 
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496) 
    ... 32 common frames omitted 
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 
    at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) 
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) 
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) 
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382) 
    ... 38 common frames omitted 

誰かが私にこの例外を取り除く手助けをすることができますか?

また、私のトラストストア(cacerts)にサイト証明書(VeriSign)を生成するために使用されたルートCAが存在するため、この例外が最初に表示される理由はわかりません。それは理由でしょうか?)。

答えて

0

問題は、プロキシ設定よりも証明書の問題に関連しているようです。

@Bean 
    @Autowired 
    public RestTemplate restTemplate(ClientHttpRequestFactory factory) 
    { 
     RestTemplate result = new RestTemplate(factory); 
     return result; 
    } 

    @Bean 
    public ClientHttpRequestFactory requestFactory() throws Exception 
    { 
     HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); 
     factory.setHttpClient(httpClient()); 
     return factory; 
    } 

    @Bean 
    public HttpClient httpClient() throws Exception 
    { 
     int timeout = new Integer(env.getProperty("web.http.client.timeout")); 
     CloseableHttpClient httpClient = null; 
       //I load a JSON where I specify the name and the PWD of keystores I want to use 
     String keystores = "keyStoreInfo.json"; 
     PoolingHttpClientConnectionManager pcm = null; 
     if(StringUtils.hasText(keystores)) 
     { 
      Resource jsonRes = new ClassPathResource(keystores); 
      if(jsonRes.exists()) 
      { 
       List<KeyStoreInfo> ksInfo = objectMapper().readValue(jsonRes.getInputStream(), new TypeReference<List<KeyStoreInfo>>() 
       { 
       }); 
       SSLContext sslCtx = SSLContext.getInstance("TLS"); 
       List<KeyManager> keymanagers = new ArrayList<KeyManager>(); 
       for (KeyStoreInfo ksi : ksInfo) 
       { 
        String keystoreName = ksi.getNomeKeyStore(); 
        String keyStorePwd = ksi.getPasswordKeyStore(); 
        if(StringUtils.hasText(keystoreName)) 
        { 
         Resource keystoreRes = new ClassPathResource(keystoreName); 
         KeyMaterial km = new KeyMaterial(keystoreRes.getInputStream(), keyStorePwd.toCharArray()); 
         KeyStore clientStore = km.getKeyStore(); 
         KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
         kmfactory.init(clientStore, keyStorePwd != null ? keyStorePwd.toCharArray() : null); 
         keymanagers.addAll(Arrays.asList(kmfactory.getKeyManagers())); 
        } 
       } 
       if(!keymanagers.isEmpty()) 
       { 

        X509TrustManager tm = new X509TrustManager() { 

         @Override 
         public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1) 
           throws CertificateException { 

         } 

         @Override 
         public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1) 
           throws CertificateException { 

         } 

         @Override 
         public java.security.cert.X509Certificate[] getAcceptedIssuers() { 

          return null; 
         } 

        };  
        sslCtx.init(keymanagers.toArray(new KeyManager[keymanagers.size()]), new TrustManager[]{tm}, null); 
        SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(sslCtx); 
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("https", sslConnectionFactory).register("http", new PlainConnectionSocketFactory()).build(); 
        pcm = new PoolingHttpClientConnectionManager(registry); 
       } 
       else 
       { 
        if(logger.isInfoEnabled()) 
        { 
         logger.info("Nessun keystore presente nel JSON di configurazione {}. Creo un PoolingHttpClientConnectionManager di default",keystores); 
        } 
        pcm = new PoolingHttpClientConnectionManager();     
       } 
      } 
     } 
     else 
     { 
      if(logger.isInfoEnabled()) 
      { 
       logger.info("Nessun keystore da caricare. Creo un PoolingHttpClientConnectionManager di default"); 
      } 
      pcm = new PoolingHttpClientConnectionManager(); 
     } 
     HttpClientBuilder hcb = HttpClientBuilder.create(); 
     pcm.closeIdleConnections(timeout, TimeUnit.MILLISECONDS); 
     RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(timeout).setSocketTimeout(timeout).setConnectTimeout(timeout).build(); 
     hcb.setDefaultRequestConfig(config); 
     hcb.setConnectionManager(pcm).setConnectionManagerShared(true); 
     boolean proxyEnable = new Boolean(env.getProperty("web.http.client.proxyEnable")); 
     if (proxyEnable) 
     { 
      int proxyPort = new Integer(env.getProperty("web.http.client.portProxy")); 
      String proxyHost = env.getProperty("web.http.client.hostProxy"); 
      BasicCredentialsProvider credentialProvider = new BasicCredentialsProvider(); 
      AuthScope scope = new AuthScope(proxyHost, proxyPort); 
      String usernameProxy = env.getProperty("web.http.client.usernameProxy"); 
      String passwordProxy = env.getProperty("web.http.client.passwordProxy"); 
      if (StringUtils.hasText(usernameProxy) && StringUtils.hasText(passwordProxy)) 
      { 

       UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(usernameProxy, passwordProxy); 
       credentialProvider.setCredentials(scope, credentials); 
      } 
      ProxyRoutePlanner proxyRoutPlanner = new ProxyRoutePlanner(new HttpHost(proxyHost, proxyPort), env.getProperty("web.http.client.urlNotProxy")); 
      hcb.setDefaultCredentialsProvider(credentialProvider).setRoutePlanner(proxyRoutPlanner); 
     } 
     WsKeepAliveStrategy cas = new WsKeepAliveStrategy(); 
     cas.setTimeout(new Long(timeout)); 
     hcb.setKeepAliveStrategy(cas); 
     httpClient = hcb.build(); 
     return httpClient; 
    } 

WsKeepAliveStrategyは次のとおりです: はとにかく私のプロジェクトで、私はこの構成使用してい

public class WsKeepAliveStrategy implements ConnectionKeepAliveStrategy 
{ 
    private Long timeout; 

    @Override 
    public long getKeepAliveDuration(HttpResponse response, HttpContext context) 
    { 
     return timeout; 
    } 

    public void setTimeout(Long timeout) 
    { 
     this.timeout = timeout; 
    } 

} 

ProxyRoutePlannerは次のとおりです。

public class ProxyRoutePlanner extends DefaultProxyRoutePlanner 
{ 

    private List<String> urlsNotProxy = null; 
    private boolean useAlwaysSuper = false; 

    public ProxyRoutePlanner(HttpHost proxy, String urlNotProxy) 
    { 
     super(proxy); 
     if (!StringUtils.hasText(urlNotProxy)) 
      this.useAlwaysSuper = true; 
     else 
     { 
      this.urlsNotProxy = Arrays.asList(urlNotProxy.split(",")); 
     } 
    } 

    @Override 
    public HttpRoute determineRoute(HttpHost host, HttpRequest request, HttpContext context) throws HttpException 
    { 

     String hostname = host.getHostName(); 
     if (this.useAlwaysSuper || this.urlsNotProxy.contains(hostname) == false) 
      return super.determineRoute(host, request, context);// Super method 
     // with proxy 
     if ("http".equals(host.getSchemeName())) 
      return new HttpRoute(host);// Direct Route 
     HttpClientContext clientContext = HttpClientContext.adapt(context); 
     RequestConfig config = clientContext.getRequestConfig(); 
     InetAddress local = config.getLocalAddress(); 
     return new HttpRoute(host, local, true); 
    } 

} 

は、私は、この設定を使用していると私は」 m問題なし

いずれにしても、 ECK証明書の種類、あなたの残りの呼び出しで

を使用する必要があり、私はそれが

アンジェロ

+0

まあ便利だ願って、私の質問は非常に正確で、あなたの答えは、それは私が言うことができるものだ、非常に広いです。また、私はあなたがあなたの休息の呼び出しで使用するために必要な証明書の種類を確認する必要がありますかどうかわからない、あなたは私が提供するURLに到達することで自分で証明書を見ることができます。証明書はVeriSignによって署名されており、私は自分のトラストストアでルートCAを見つけることができます。とにかく、私はブラウザを実装していないので、私はホスト認証を無効にしようとしています。 – Tristan

+0

私は設定を投稿しました。この設定を使用することで、証明書とプロキシの両方の使用に問題はありません。あなたは自由に使用することも、使用しないこともできます。あなたのケースでは、例外はかなり明確です..プロキシではなく証明書チェーンなので、私があなたに提案しているのはそれを確認することです –

+0

あなたは質問のタイトルに答えています。あなたは書いていますか?推測してはいけません。自分で証明書を見て、正当な人であることを確認してください。 – Tristan

関連する問題