Ignorer SSL cert auto-signé en utilisant le client Jersey

j'utilise la bibliothèque client De Jersey pour faire des tests contre un service de repos fonctionnant sur jboss. J'ai fait configurer HTTPS sur le serveur (en cours d'exécution sur localhost), en utilisant un cert auto-signé.

Mais chaque fois que j'exécute mes tests avec l'url https j'obtiens l'erreur suivante:

com.sun.jersey.api.client.ClientHandlerException: 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 com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:131)
    at com.sun.jersey.api.client.Client.handle(Client.java:629)
    at com.sun.jersey.oauth.client.OAuthClientFilter.handle(OAuthClientFilter.java:137)
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:601)
    at com.sun.jersey.api.client.WebResource.access0(WebResource.java:74)
    at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:459)
    at test.helper.Helper.sendSignedRequest(Helper.java:174)
    ... And so on

je sais que c'est parce que mon certificat auto signé n'est pas dans le keystore java. Est - ce qu'il y a un moyen que je puisse faire le Client ne pas vérifier la validité du certificat ssl et juste l'utiliser quel que soit?

ce code ne sera jamais exécuté que contre des serveurs de test, donc je ne veux pas aller à l'embêtement d'ajouter de nouveaux certs de confiance chaque fois que nous mettons en place un nouveau serveur de test.

voici le code qui fait l'appel:

OAuthParameters params = new OAuthParameters();

// baseline OAuth parameters for access to resource
params.signatureMethod(props.getProperty("signature_method"));
params.consumerKey(props.getProperty("consumer_key"));
params.setToken(props.getProperty("token"));
params.setVersion("1.0");
params.nonce();

// OAuth secrets to access resource
OAuthSecrets secrets = new OAuthSecrets();
secrets.consumerSecret(props.getProperty("consumer_secret"));
secrets.setTokenSecret(props.getProperty("token_secret"));

// Jersey client to make REST calls to token services
Client client = Client.create();

// OAuth test server resource
WebResource resource = client.resource(props.getProperty("url"));

// if parameters and secrets remain static, filter cab be added to each web resource
OAuthClientFilter filter = new OAuthClientFilter(client.getProviders(), params, secrets);

// filter added at the web resource level
resource.addFilter(filter);
WebResource.Builder wbr = resource.getRequestBuilder().accept(props.getProperty("accept"));

return wbr.get(ClientResponse.class);

Toute aide serait grandement appréciée.

53
demandé sur Chris Salij 2011-05-18 20:32:24

11 réponses

après un peu de recherche et de chalutage à travers quelques vieilles questions sur l'écoulement des piles, j'ai trouvé une solution dans une question déjà posée:

voici le code que j'ai fini par utiliser.

// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager(){
    public X509Certificate[] getAcceptedIssuers(){return null;}
    public void checkClientTrusted(X509Certificate[] certs, String authType){}
    public void checkServerTrusted(X509Certificate[] certs, String authType){}
}};

// Install the all-trusting trust manager
try {
    SSLContext sc = SSLContext.getInstance("TLS");
    sc.init(null, trustAllCerts, new SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
    ;
}
77
répondu Chris Salij 2017-05-23 12:34:38

Pour Jersey 2.* (Testé sur 2.7) et java 8:

import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 

public static Client ignoreSSLClient() throws Exception {

    SSLContext sslcontext = SSLContext.getInstance("TLS");

    sslcontext.init(null, new TrustManager[]{new X509TrustManager() {
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
        public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
    }}, new java.security.SecureRandom());

    return ClientBuilder.newBuilder()
                        .sslContext(sslcontext)
                        .hostnameVerifier((s1, s2) -> true)
                        .build();
}
42
répondu eitan 2018-01-16 10:00:02

j'ai eu le même problème adn ne voulait pas que ce soit défini globalement, donc j'ai utilisé le même code TrustManager et SSLContext comme ci-dessus, j'ai juste changé le Client à créer avec des propriétés spéciales

 ClientConfig config = new DefaultClientConfig();
 config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(
     new HostnameVerifier() {
         @Override
         public boolean verify( String s, SSLSession sslSession ) {
             // whatever your matching policy states
         }
     }
 ));
 Client client = Client.create(config);
10
répondu Ransom Briggs 2013-07-09 13:59:55

ce code ne sera jamais exécuté que contre des serveurs de test donc je ne veux pas pour aller à l'ennui d'ajouter de nouveaux certs de confiance chaque fois que nous mettons en place un nouveau serveur de test.

C'est le genre de code qui finira par trouver son chemin dans la production (si ce n'est pas de vous, quelqu'un d'autre qui lit cette question va copier et coller les gestionnaires de confiance non sécurisés qui ont été suggérés dans leurs applications). C'est tellement facile d'oublier supprimer ce genre de code quand vous avez une date limite, car il n'apparaît pas comme un problème.

si vous craignez d'avoir à ajouter de nouveaux certificats chaque fois que vous avez un serveur de test, créez votre propre petite CA, émettez tous les certificats pour les serveurs de test qui utilisent cette CA et importez ce certificat CA dans votre boutique de confiance client. (Même si vous ne traitez pas de choses comme la révocation de certificats en ligne dans un environnement local, c'est certainement mieux que d'utiliser une fiducie manager qui laisse passer n'importe quoi.)

il y a des outils pour vous aider à le faire, par exemple TinyCA ou XCA .

8
répondu Bruno 2013-08-14 13:18:26

comme je suis nouveau à stackoverflow et que j'ai moins de réputation pour commenter les réponses des autres, je mets la solution suggérée par Chris Salij avec quelques modifications qui ont fonctionné pour moi.

            SSLContext ctx = null;
            TrustManager[] trustAllCerts = new X509TrustManager[]{new X509TrustManager(){
                public X509Certificate[] getAcceptedIssuers(){return null;}
                public void checkClientTrusted(X509Certificate[] certs, String authType){}
                public void checkServerTrusted(X509Certificate[] certs, String authType){}
            }};
            try {
                ctx = SSLContext.getInstance("SSL");
                ctx.init(null, trustAllCerts, null);
            } catch (NoSuchAlgorithmException | KeyManagementException e) {
                LOGGER.info("Error loading ssl context {}", e.getMessage());
            }

            SSLContext.setDefault(ctx);
8
répondu Mukesh 2014-12-10 10:36:46

pour quiconque sur Jersey 2.x Sans lambdas, utilisez ceci:

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
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 javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;

public static Client getUnsecureClient() throws Exception 
{
    SSLContext sslcontext = SSLContext.getInstance("TLS");
    sslcontext.init(null, new TrustManager[]{new X509TrustManager() 
    {
            public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{}
            public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{}
            public X509Certificate[] getAcceptedIssuers()
            {
                return new X509Certificate[0];
            }

    }}, new java.security.SecureRandom());


    HostnameVerifier allowAll = new HostnameVerifier() 
    {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

    return ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier(allowAll).build();
}

Testé avec jersey-client 2.11 sur JRE 1.7 .

4
répondu masi 2017-01-27 17:58:14

il suffit d'ajouter le même code avec les importations. Contient également le code non implémenté qui est nécessaire pour la compilation. J'ai d'abord eu du mal à trouver ce qui a été importé pour ce code. Ajouter également le bon paquet pour le X509Certificate. Reçu ce travail avec l'essai et l'erreur:

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.security.cert.CertificateException;
import javax.security.cert.X509Certificate;
import javax.ws.rs.core.MultivaluedMap;

 TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {

     public java.security.cert.X509Certificate[] getAcceptedIssuers() {
         java.security.cert.X509Certificate[] chck = null;
         ;
         return chck;
     }

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

     }

     public void checkClientTrusted(X509Certificate[] arg0, String arg1)
             throws CertificateException {

     }

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

     }

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

     }
 } };

 // Install the all-trusting trust manager
 try {
     SSLContext sc = SSLContext.getInstance("TLS");
     sc.init(null, trustAllCerts, new SecureRandom());
     HttpsURLConnection
     .setDefaultSSLSocketFactory(sc.getSocketFactory());
 } catch (Exception e) {
     ;
 }
3
répondu prakash krishnan 2014-12-30 15:40:58

Pour Jersey 2.* :

Client client = ClientBuilder.newBuilder()
                .hostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                }).build();

- > https://jersey.java.net/documentation/latest/migration.html

1
répondu Marcelo C. 2016-02-16 15:59:54

Pour Jersey 1.X

    TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {

        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {}

        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {}

        public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
            // or you can return null too
            return new java.security.cert.X509Certificate[0];
        }
    }};


    SSLContext sc = SSLContext.getInstance("TLS");
    sc.init(null, trustAllCerts, new SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
        public boolean verify(String string, SSLSession sslSession) {
            return true;
        }
    });
0
répondu grep 2016-12-29 09:24:55

j'ai remarqué que lors de l'utilisation de la configuration du client http Apache avec un gestionnaire de mise en commun, la réponse acceptée ne fonctionne pas.

dans ce cas, il semble que les setters ClientConfig.sslContext et ClientConfig.hostnameVerifier soient ignorés en silence. Ainsi, si vous utilisez la mise en commun des connexions avec la configuration client http apache, vous devriez pouvoir utiliser le code suivant pour faire en sorte que la vérification ssl soit ignorée:

  ClientConfig clientConfig = new ClientConfig();
  // ... configure your clientConfig
  SSLContext sslContext = null;
  try {
    sslContext = SSLContext.getInstance("SSL");
    sslContext.init(null, new TrustManager[] {
        new X509TrustManager() {
          @Override
          public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {
          }

          @Override
          public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
          }

          @Override
          public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[] {};
          }
        }
    }, null);
  } catch (NoSuchAlgorithmException e) {
    //logger.debug("Ignoring 'NoSuchAlgorithmException' while ignoring ssl certificate validation.");
  } catch (KeyManagementException e) {
    //logger.debug("Ignoring 'KeyManagementException' while ignoring ssl certificate validation.");
  }
  Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
      .register("http", PlainConnectionSocketFactory.getSocketFactory())
      .register("https", new SSLConnectionSocketFactory(sslContext, new AbstractVerifier() {
        @Override
        public void verify(String host, String[] cns, String[] subjectAlts) {
        }
      }))
      .build();
  connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
  clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager);
  return ClientBuilder.newClient(clientConfig);
0
répondu Nicholas DiPiazza 2018-09-27 16:49:49

a marché pour moi avec ce code. Peut être pour Java 1.7

    TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }

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

        }

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

        }
    }};

    // Install the all-trusting trust manager
    try {
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (Exception e) {
        ;
    }
-3
répondu Tapas 2013-08-14 12:34:26