2010-11-01 448 views
28

我在兩臺不同的機器上有兩個基於Spring的Web應用程序A和B.在Spring RestTemplate中禁用SSL證書驗證

我想從Web應用程序A到Web應用程序B進行https呼叫,但是我在機器B中使用了自簽名證書。所以我的HTTPS請求失敗。

如何在Spring中使用RestTemplate時禁用https證書驗證?我想禁用驗證,因爲兩者的web應用程序A和B都在內部網絡中,但數據傳輸已經發生了HTTPS

回答

26

您需要添加什麼是自定義HostnameVerifier類繞過證書驗證並返回true

HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { 
      public boolean verify(String hostname, SSLSession session) { 
       return true; 
      } 
     }); 

這需要適當地放置在您的代碼中。

+0

我使用Spring的RestTemplate類,你知道我在RestTemplate中可以做到嗎? – Ram 2010-11-02 10:43:03

+6

其實這是在RestTemplate之外。 http://forum.springsource.org/showthread.php?t=60854上提供了一些示例代碼。也看看http://stackoverflow.com/questions/1725863/ssl-handshake-issue-using-spring-resttemplate – Raghuram 2010-11-02 11:49:18

+0

看到這些鏈接,並得到它的工作。謝謝:) – Ram 2010-11-02 14:33:41

6
Add my response with cookie : 

    public static void main(String[] args) { 
      MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); 
      params.add("username", testUser); 
      params.add("password", testPass); 
NullHostnameVerifier verifier = new NullHostnameVerifier(); 
      MySimpleClientHttpRequestFactory requestFactory = new MySimpleClientHttpRequestFactory(verifier , rememberMeCookie); 
      ResponseEntity<String> response = restTemplate.postForEntity(appUrl + "/login", params, String.class); 

      HttpHeaders headers = response.getHeaders(); 
      String cookieResponse = headers.getFirst("Set-Cookie"); 
      String[] cookieParts = cookieResponse.split(";"); 
      rememberMeCookie = cookieParts[0]; 
      cookie.setCookie(rememberMeCookie); 

      requestFactory = new MySimpleClientHttpRequestFactory(verifier,cookie.getCookie()); 
      restTemplate.setRequestFactory(requestFactory); 
    } 


    public class MySimpleClientHttpRequestFactory extends SimpleClientHttpRequestFactory { 

     private final HostnameVerifier verifier; 
     private final String cookie; 

     public MySimpleClientHttpRequestFactory(HostnameVerifier verifier ,String cookie) { 
      this.verifier = verifier; 
      this.cookie = cookie; 
     } 

     @Override 
     protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException { 
      if (connection instanceof HttpsURLConnection) { 
       ((HttpsURLConnection) connection).setHostnameVerifier(verifier); 
       ((HttpsURLConnection) connection).setSSLSocketFactory(trustSelfSignedSSL().getSocketFactory()); 
       ((HttpsURLConnection) connection).setAllowUserInteraction(true); 
       String rememberMeCookie = cookie == null ? "" : cookie; 
       ((HttpsURLConnection) connection).setRequestProperty("Cookie", rememberMeCookie); 
      } 
      super.prepareConnection(connection, httpMethod); 
     } 

     public SSLContext 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); 
       return ctx; 
      } catch (Exception ex) { 
       ex.printStackTrace(); 
      } 
      return null; 
     } 

    } 


    public class NullHostnameVerifier implements HostnameVerifier { 
      public boolean verify(String hostname, SSLSession session) { 
       return true; 
      } 
     } 
+0

NullHostnameVerifier verifier = new NullHostnameVerifier();你可以看到記得我的cookie是一個字符串 – 2016-01-10 06:07:39

19
@Bean 
public RestTemplate restTemplate() 
       throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { 
    TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true; 

    SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom() 
        .loadTrustMaterial(null, acceptingTrustStrategy) 
        .build(); 

    SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext); 

    CloseableHttpClient httpClient = HttpClients.custom() 
        .setSSLSocketFactory(csf) 
        .build(); 

    HttpComponentsClientHttpRequestFactory requestFactory = 
        new HttpComponentsClientHttpRequestFactory(); 

    requestFactory.setHttpClient(httpClient); 
    RestTemplate restTemplate = new RestTemplate(requestFactory); 
    return restTemplate; 
} 
+0

魅力.......... – Valath 2018-02-22 11:02:00

9

從本質上講,你需要做兩件事情是使用信任所有證書一個定製TrustStrategy,並且還使用NoopH​​ostnameVerifier()禁用主機名驗證。這裏是所有相關進口的代碼:

import java.security.KeyManagementException; 
import java.security.KeyStoreException; 
import java.security.NoSuchAlgorithmException; 
import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 
import javax.net.ssl.SSLContext; 
import org.apache.http.conn.ssl.NoopHostnameVerifier; 
import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 
import org.apache.http.conn.ssl.TrustStrategy; 
import org.apache.http.impl.client.CloseableHttpClient; 
import org.apache.http.impl.client.HttpClients; 
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 
import org.springframework.web.client.RestTemplate; 

public RestTemplate getRestTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { 
    TrustStrategy acceptingTrustStrategy = new TrustStrategy() { 
     @Override 
     public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { 
      return true; 
     } 
    }; 
    SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build(); 
    SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier()); 
    CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build(); 
    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); 
    requestFactory.setHttpClient(httpClient); 
    RestTemplate restTemplate = new RestTemplate(requestFactory); 
    return restTemplate; 
} 
+1

謝謝,這對我有用! – Humoyun 2017-11-15 07:04:13

+1

TrustStrategy acceptingTrustStrategy =(X509Certificate [] x509Certificates,String s) - > true; – Humoyun 2017-11-15 07:05:10

+1

謝謝,這救了我的命。所有其他方法(使用keytool,http://blog.codeleak.pl/2016/02/skip-ssl-certificate-verification-in.html和約5〜6個其他stackoverflow帖子添加導出的.crt到使用keytool的導出.crt,包括答案在這一個)失敗了,花了我7個小時的時間。這個答案是我最後的希望,謝謝。 – 2018-01-27 12:20:40

0

你可以在HTTPClient API中使用它。

public RestTemplate getRestTemplateBypassingHostNameVerifcation() { 
    CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build(); 
    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); 
    requestFactory.setHttpClient(httpClient); 
    return new RestTemplate(requestFactory); 

}