2016-04-17 40 views
10

Sto tentando di inviare una richiesta al seguente indirizzo. Il certificato non è valido e vorrei ignorarlo. Ho scritto il seguente codice in base alla mia ricerca su 1, 2 ma non riesco a completarlo. Sto usando Java 1.7,È necessario ignorare il certificato quando si utilizza restTemplate

https://api.stubhubsandbox.com/search/catalog/events/v3 

Codice

private static final TrustManager[] UNQUESTIONING_TRUST_MANAGER = new TrustManager[]{ 
    new X509TrustManager() { 
     public java.security.cert.X509Certificate[] getAcceptedIssuers(){ 
      return null; 
     } 
     public void checkClientTrusted(X509Certificate[] certs, String authType){} 
     public void checkServerTrusted(X509Certificate[] certs, String authType){} 
     public void checkClientTrusted(
       java.security.cert.X509Certificate[] arg0, String arg1) 
       throws CertificateException { 
      // TODO Auto-generated method stub 

     } 
     public void checkServerTrusted(
       java.security.cert.X509Certificate[] arg0, String arg1) 
       throws CertificateException { 
      // TODO Auto-generated method stub 

     } 
    } 
}; 

public static void main(String[] args) { 
    TrustStrategy acceptingTrustStrategy = 

    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); 
    String url = "https://api.stubhubsandbox.com/search/catalog/events/v3"; 
    RestTemplate rest = new RestTemplate(); 
    Map<String, String> mvm = new HashMap<String, String>(); 
    mvm.put("Authorization", "Bearer TOKEEEEEEEN"); 
    Object object = rest.postForObject(url, null, Object.class, mvm); 
    System.err.println("done"); 


} 
+0

Mi manca l'impostazione 'UNQUESTIONING_TRUST_MANAGER' a 'SSLContext' nel tuo codice. –

+0

@MichalFoksa come impostarlo? Inoltre ho jdk 1.7 ma una parte del mio codice è 1.8 non so come risolverlo. –

+0

Si sta forzando un'istanza 'RestTemplate' per accettare certificati autofirmati su RestTemplate restTemplate = new RestTemplate (requestFactory);'. Ma poi hai RestTemplate rest = new RestTemplate(); rest.postForObject (url, null, Object.class, mvm); '. Ciò significa che l'effettiva chiamata REST utilizza un'istanza 'RestTemplate' che non accetta il certificato autofirmato. Se invece si utilizza 'restTemplate.postForObject', la chiamata verrà eseguita. – manish

risposta

5

Non sono sicuro se le cose sono cambiate dopo JDK6, ma l'ultima volta stavo cercando di fare questo abbiamo bisogno di importare il certificato SSL per il keystore di il JAVA_HOME utilizzato per eseguire i programmi che utilizzano il trusted ssl.

Innanzitutto, è necessario esportare il certificato in un file. In Windows, è possibile utilizzare qualsiasi browser per salvare il certificato SSL nell'archivio dei certificati personali e quindi eseguire mmc, aggiungere certificati snap-in (File/Aggiungi rimozione snap-in) e salvare il certificato su disco.

Quindi è necessario importare il certificato per i cacer del dominio trusted utilizzando keytool. Ma è necessario importarlo nel keystore utilizzato da java_home durante l'esecuzione dei programmi in alto.

Il comando seguente aggiungerà il file di certificato "mycertificate.cer" al keystore nel file "cacerts.jks". L'alias è "webservice":

"%JAVA_HOME%\bin\keytool" -import -trustcacerts -alias webservice -file mycertificate.cer -keystore cacerts.jks 

Di solito, la password dell'archivio chiavi è "changeit", senza virgolette. Cambialo per uso produzione

+0

Grazie per la risposta, so che potrebbe essere necessario scaricare il certificato, ma mi stavo chiedendo se è possibile ignorare il certificato in primo luogo. –

15

Come avrai notato, Spring's RestTemplate delega tutti i materiali relativi a HTTP (S) all'implementazione sottostante di ClientHttpRequestFactory. Dal momento che si sta utilizzando la HttpClient based realizzazione, qui ci sono un paio di utili SO link su come raggiungere questo obiettivo per l'interno HttpClient:

A quanto pare, a partire dalla versione 4.4, questo può essere fatto come:

CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build(); 
+0

Grazie per la risposta, non è possibile utilizzare restTemplate? Ho già provato la soluzione proposta per il tuo secondo punto elenco ma non riuscivo a farlo funzionare per JDK 1.7 –

+0

RestTemplate è solo un wrapper su un oggetto 'ClientHttpRequestFactory'. Sembra che tu stia già utilizzando l'implementazione basata su 'HttpClient', quindi tutto ciò che devi fare è cambiare il modo in cui costruisci il tuo HttpClient interno. –

4

Per bypassare i controlli SSL in diversi progetti di primavera, io sempre riutilizzare una classe SSLUtils che ho scritto (o trovato) qualche tempo fa in congiunzione con RestTemplate di primavera. Utilizzando la classe fornita di seguito, è sufficiente chiamare il metodo statico SSLUtils.turnOffSslChecking() prima di inviare la richiesta.

import javax.net.ssl.*; 
import java.security.*; 
import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 

public final class SSLUtil{ 

    static { 
     //for localhost testing only 
     javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
     new javax.net.ssl.HostnameVerifier(){ 

      public boolean verify(String hostname, 
        javax.net.ssl.SSLSession sslSession) { 
       if (hostname.equals("localhost")) { 
        return true; 
       } 
       return false; 
      } 
     }); 
    } 

    private static final TrustManager[] UNQUESTIONING_TRUST_MANAGER = new TrustManager[]{ 
      new X509TrustManager() { 
       public java.security.cert.X509Certificate[] getAcceptedIssuers(){ 
        return null; 
       } 
       public void checkClientTrusted(X509Certificate[] certs, String authType){} 
       public void checkServerTrusted(X509Certificate[] certs, String authType){} 
      } 
     }; 

    public static void turnOffSslChecking() throws NoSuchAlgorithmException, KeyManagementException { 
     // Install the all-trusting trust manager 
     final SSLContext sc = SSLContext.getInstance("SSL"); 
     sc.init(null, UNQUESTIONING_TRUST_MANAGER, null); 
     HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 
    } 

    public static void turnOnSslChecking() throws KeyManagementException, NoSuchAlgorithmException { 
     // Return it to the initial state (discovered by reflection, now hardcoded) 
     SSLContext.getInstance("SSL").init(null, null, null); 
    } 

    private SSLUtil(){ 
     throw new UnsupportedOperationException("Do not instantiate libraries."); 
    } 
} 

Provalo. Spero che funzioni e sia una soluzione facile per te.

+0

Grazie per quello - posso garantire che il tuo codice per disabilitare il controllo del nome host funzioni. Vale la pena sottolineare che questo funziona solo quando si utilizza il RestTemplate predefinito che utilizza la libreria HTTP HttpURLConnection Java di base. Per il caso più comune di utilizzo di Apache HttpComponents è un po 'più complicato. Ho finito per creare un profilo "locale" che utilizzava un RestTemplate di base con sicurezza disabilitata e un RestTemplate con Apache HttpComponents con sicurezza completa per tutti gli altri profili –

-1

È possibile utilizzare questo codice:

@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; 
} 

in Java 7 sostituire l'espressione lambda con:

 TrustStrategy acceptingTrustStrategy = new TrustStrategy() { 
     @Override public boolean isTrusted(X509Certificate[] x509Certificates, String s) 
         throws CertificateException { 
      return true; 
     } 
    }; 
2

Aggiungere il SSLContext e X509TrustManager e la HostnameVerifier casi al http ClientBuilders. Possono essere per esempio (dato il mio esempio)

  1. HttpClientBuilder con HttpComponentsClientHttpRequestFactory
  2. OkHttpClient.Builder con OkHttp3ClientHttpRequestFactory

Ecco il codice di esempio per Apache HttpClient & OkHttpClient. Il suo scopo per demo, ma è possibile utilizzarlo

Apache HttpClient

RestTemplate restTemplate = new RestTemplate(SSLClientFactory.getClientHttpRequestFactory(HttpClientType.HttpClient)); 

e OkHttpClient

RestTemplate restTemplate = new RestTemplate(SSLClientFactory.getClientHttpRequestFactory(HttpClientType.OkHttpClient)); 

La classe SSLClientFactory è personalizzato qui

import java.security.KeyManagementException; 
import java.security.NoSuchAlgorithmException; 
import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 
import java.util.concurrent.TimeUnit; 

import javax.net.ssl.HostnameVerifier; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.SSLSession; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 

import org.apache.http.impl.client.HttpClientBuilder; 
import org.springframework.http.client.ClientHttpRequestFactory; 
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; 
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; 

import okhttp3.OkHttpClient; 

public abstract class SSLClientFactory { 

    private static boolean allowUntrusted = false; 
    private static final long LOGIN_TIMEOUT_SEC = 10; 
    private static HttpClientBuilder closeableClientBuilder = null; 
    private static OkHttpClient.Builder okHttpClientBuilder = null; 

    public enum HttpClientType{ 
     HttpClient, 
     OkHttpClient 
    } 


    public static synchronized ClientHttpRequestFactory getClientHttpRequestFactory(HttpClientType httpClientType){ 

     ClientHttpRequestFactory requestFactory = null; 

     SSLContext sslContext = SSLClientFactory.getSSlContext(); 

     if(null == sslContext){ 
      return requestFactory; 
     } 

     switch (httpClientType) { 

     case HttpClient: 
      closeableClientBuilder = HttpClientBuilder.create(); 

      //Add the SSLContext and trustmanager 
      closeableClientBuilder.setSSLContext(getSSlContext()); 
      //add the hostname verifier 
      closeableClientBuilder.setSSLHostnameVerifier(gethostnameVerifier()); 

      requestFactory = new HttpComponentsClientHttpRequestFactory(closeableClientBuilder.build()); 

      break; 
     case OkHttpClient: 
      okHttpClientBuilder = new OkHttpClient().newBuilder().readTimeout(LOGIN_TIMEOUT_SEC, TimeUnit.SECONDS); 

      //Add the SSLContext and trustmanager 
      okHttpClientBuilder.sslSocketFactory(getSSlContext().getSocketFactory(), getTrustManager()); 
      //add the hostname verifier 
      okHttpClientBuilder.hostnameVerifier(gethostnameVerifier()); 

      requestFactory = new OkHttp3ClientHttpRequestFactory(okHttpClientBuilder.build()); 

      break; 
     default: 
      break; 
     } 

     return requestFactory; 

    } 


    private static SSLContext getSSlContext(){ 



     final TrustManager[] trustAllCerts = new TrustManager[]{getTrustManager()}; 

     SSLContext sslContext = null; 
     try { 

      sslContext = SSLContext.getInstance("SSL"); 
      sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); 

     } catch (NoSuchAlgorithmException | KeyManagementException e) { 
      e.printStackTrace(); 
     } 



     return sslContext; 

    } 

    private static X509TrustManager getTrustManager(){ 

     final X509TrustManager trustManager = new X509TrustManager() { 

      @Override 
      public X509Certificate[] getAcceptedIssuers() { 
       X509Certificate[] cArrr = new X509Certificate[0]; 
       return cArrr; 
      } 

      @Override 
      public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
       // TODO Auto-generated method stub 

      } 

      @Override 
      public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
       // TODO Auto-generated method stub 

      } 
     }; 

     return trustManager; 
    } 

    private static HostnameVerifier gethostnameVerifier(){ 

     HostnameVerifier hostnameVerifier = new HostnameVerifier() { 

      @Override 
      public boolean verify(String arg0, SSLSession arg1) { 
       return true; 
      } 
     }; 

     return hostnameVerifier; 

    } 

}