2016-04-17 2 views
10

Я пытаюсь отправить запрос по следующему адресу. Сертификат недействителен, и я хотел бы проигнорировать его. Я написал следующий код, основанный на моих исследованиях по 1, 2, но я не могу его завершить. Я использую Java 1.7,Необходимо игнорировать сертификат при использовании restTemplate

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

код

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

Я скучаю по настройке 'UNQUESTIONING_TRUST_MANAGER' в 'SSLContext' в вашем коде. –

+0

@MichalFoksa как установить это? Также у меня есть jdk 1.7, но часть моего кода 1,8 не уверен, как его исправить. –

+0

Вы вынуждаете экземпляр 'RestTemplate' принимать самозаверяющие сертификаты в' RestTemplate restTemplate = new RestTemplate (requestFactory); '. Но тогда у вас есть RestTemplate rest = new RestTemplate(); rest.postForObject (url, null, Object.class, mvm); '. Это означает, что в действительном вызове REST используется экземпляр 'RestTemplate', который не принимает самозаверяющий сертификат. Если вместо этого вы используете 'restTemplate.postForObject', ваш звонок будет проходить. – manish

ответ

5

Не уверен, что если что-то изменилось после того, как JDK6, но последний раз, когда я пытался сделать это нам нужно импортировать сертификат SSL в хранилище ключей от JAVA_HOME используется для запуска программ с использованием доверенного ssl.

Прежде всего, вам нужно будет экспортировать сертификат в файл. В окнах вы можете использовать любой браузер для сохранения сертификата SSL в своем хранилище личных сертификатов, а затем запустить mmc, добавить сертификаты snapin (File/Add Remove Snapin) и сохранить сертификат на диск.

Затем вам необходимо импортировать сертификат в доверенные доменные cacerts, используя keytool. Но вам нужно импортировать его в хранилище ключей, которое использует java_home при запуске ваших программ выше.

Приведенная ниже команда добавит файл сертификата «mycertificate.cer» в хранилище ключей в файле «cacerts.jks». Псевдоним "вебсервис":

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

Обычно Keystore пароль "changeit", без кавычек. Измените его для использования в промышленности

+0

Спасибо за ваш ответ, я знаю, возможно, потребуется загрузить сертификат, но мне просто интересно, можно ли вообще игнорировать сертификат. –

15

Как вы, возможно, заметили, Spring RestTemplate делегирует все связанные с HTTP (S) вещи в базовую реализацию ClientHttpRequestFactory. Так как вы используете -На реализацию HttpClient, вот несколько полезных ссылок SO о том, как добиться этого для внутреннего HttpClient:

По-видимому, начиная с версии 4.4, это можно сделать следующим образом:

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

Спасибо за ваш ответ, нельзя ли вообще использовать restTemplate? Я уже пробовал предлагаемое решение вашей второй маркерной точки, но не смог заставить ее работать для JDK 1.7. –

+0

RestTemplate - это просто оболочка над «ClientHttpRequestFactory». Вы, похоже, уже используете реализацию на основе HttpClient, поэтому все, что вам нужно сделать, это изменить способ создания вашего внутреннего HttpClient. –

4

Чтобы обойти проверки SSL в нескольких весенних проектах, я всегда повторно использовать класс SSLUtils, который я написал (или нашел) некоторое время назад вместе с SpringTemplate Spring. Используя приведенный ниже класс, вам просто нужно вызвать статический метод SSLUtils.turnOffSslChecking(), прежде чем отправлять запрос.

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."); 
    } 
} 

Дайте ему попробовать. Надеюсь, это сработает и получится как простое решение для вас.

+0

Спасибо за это - я могу поручиться, что ваш код для отключения проверки имени хоста работает. Стоит отметить, что это работает только при использовании RestTemplate по умолчанию, в котором используется базовая HTTP-библиотека Java HttpURLConnection. Для более распространенного случая использования Apache HttpComponents это довольно сложно. Я закончил создание «локального» профиля, который использовал базовый RestTemplate с отключенной защитой, и RestTemplate с Apache HttpComponents с полной безопасностью для всех других профилей –

-1

Вы можете использовать этот код:

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

в Java 7 заменить лямбда-выражения с:

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

Добавьте SSLContext и X509TrustManager и HostnameVerifier экземпляры в HTTP ClientBuilders. Они могут быть, например, (учитывая мой пример)

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

Вот пример кода для Apache HttpClient & OkHttpClient. Его для демонстрационной цели, но вы можете использовать его

Apache HttpClient

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

и OkHttpClient

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

SSLClientFactory является пользовательский класс здесь

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; 

    } 

} 
Смежные вопросы