web-dev-qa-db-fra.com

Nécessité d'ignorer le certificat lors de l'utilisation de restTemplate

J'essaie d'envoyer une demande à l'adresse suivante. Le certificat n'est pas valide et j'aimerais l'ignorer. J'ai écrit le code suivant sur la base de mes recherches sur 1 , 2 mais je ne peux pas le compléter. J'utilise Java 1.7,

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

Code

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


}
14
Daniel Newtown

Comme vous l'avez peut-être remarqué, la variable RestTemplate de Spring délègue tous les éléments liés à HTTP (S) à l'implémentation sous-jacente de ClientHttpRequestFactory. Puisque vous utilisez l'implémentation basée sur HttpClient, voici quelques liens utiles SO sur la manière de réaliser cela pour la variable interne HttpClient:

Apparemment, depuis la version 4.4, cela peut être fait comme suit:

CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
18
Costi Ciudatu

Pour contourner les vérifications SSL dans plusieurs projets spring, je réutilise toujours une classe SSLUtils que j'ai écrite (ou trouvée) il y a quelque temps en conjonction avec RestTemplate de spring. En utilisant la classe fournie ci-dessous, il vous suffit d’appeler la méthode statique SSLUtil.turnOffSslChecking() avant d’envoyer votre demande. 

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

Essaie. J'espère que cela fonctionne et s'avère être une solution facile pour vous.

7
mika

Pas sûr si les choses ont changé après jdk6, mais la dernière fois que j'essayais de le faire, nous devions importer le certificat SSL dans le magasin de clés de Java_HOME utilisé pour exécuter les programmes utilisant le fichier SSL sécurisé.

Tout d'abord, vous devrez exporter le certificat dans un fichier. Sous Windows, vous pouvez utiliser n’importe quel navigateur pour enregistrer le certificat SSL dans votre magasin de certificats personnel, puis exécuter mmc, ajouter un certificat en tant que composant logiciel enfichable (Fichier/Ajouter Supprimer le composant logiciel enfichable) et enregistrer le certificat sur le disque.

Ensuite, vous devez importer le certificat dans un compte de domaine approuvé à l’aide de keytool . Mais vous devez l'importer dans le fichier de clés utilisé par votre Java_home lors de l'exécution de vos programmes ci-dessus. 

La commande ci-dessous ajoutera le fichier de certificat "mycertificate.cer" au magasin de clés du fichier "cacerts.jks". L'alias est "webservice":

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

Généralement, le mot de passe du magasin de clés est "changeit", pas de guillemets. Le changer pour une utilisation en production

7
chrisl08

Ajoutez les instances SSLContext et X509TrustManager et HostnameVerifier à http ClientBuilders . Elles peuvent être par exemple (à mon exemple)

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

Voici l'exemple de code pour Apache HttpClient & OkHttpClient. Son à des fins de démonstration, mais vous pouvez l'utiliser

Apache HttpClient

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

et OkHttpClient

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

SSLClientFactory est une classe personnalisée ici

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;

    }

}
7
Novice

Si vous utilisez Apache httpClient 4.5, procédez comme suit:

public static void main(String... args)  {

    try (CloseableHttpClient httpclient = createAcceptSelfSignedCertificateClient()) {
        HttpGet httpget = new HttpGet("https://example.com");
        System.out.println("Executing request " + httpget.getRequestLine());

        httpclient.execute(httpget);
        System.out.println("----------------------------------------");
    } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException | IOException e) {
        throw new RuntimeException(e);
    }
}

private static CloseableHttpClient createAcceptSelfSignedCertificateClient()
        throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {

    // use the TrustSelfSignedStrategy to allow Self Signed Certificates
    SSLContext sslContext = SSLContextBuilder
            .create()
            .loadTrustMaterial(new TrustSelfSignedStrategy())
            .build();

    // we can optionally disable hostname verification. 
    // if you don't want to further weaken the security, you don't have to include this.
    HostnameVerifier allowAllHosts = new NoopHostnameVerifier();

    // create an SSL Socket Factory to use the SSLContext with the trust self signed certificate strategy
    // and allow all hosts verifier.
    SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, allowAllHosts);

    // finally create the HttpClient using HttpClient factory methods and assign the ssl socket factory
    return HttpClients
            .custom()
            .setSSLSocketFactory(connectionFactory)
            .build();
}
1
Brijesh Patel