Ignorer le certificate ssl auto-signé à l’aide de Jersey Client

J’utilise la bibliothèque Jersey Client pour exécuter des tests sur un service de repos exécuté sur jboss. J’ai https configuré correctement sur le serveur (exécuté sur localhost), en utilisant un certificate auto-signé.

Cependant, chaque fois que je lance 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 certificateion 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.access$200(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 certificate auto-signé n’est pas dans le keystore java. Y a-t-il un moyen de faire en sorte que le Client ne vérifie pas la validité du certificate SSL et ne l’utilise pas?

Ce code ne sera exécuté que sur des serveurs de test. Je ne veux donc pas append de nouveaux certificates de confiance chaque fois que nous configurons 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.

Après quelques recherches et recherches sur certaines anciennes questions de stackoverflow, j’ai trouvé une solution dans une question SO précédemment posée:

  • Question: Certificats de client Java sur HTTPS / SSL
  • Répondre aux certificates de client Java via HTTPS / SSL

Voici le code que j’ai fini par utiliser.

 // Create a trust manager that does not validate certificatee chains TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager(){ public X509Certificate[] getAcceptedIssuers(){return null;} public void checkClientTrusted(X509Certificate[] certs, Ssortingng authType){} public void checkServerTrusted(X509Certificate[] certs, Ssortingng 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) { ; } 

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, Ssortingng arg1) throws CertificateException {} public void checkServerTrusted(X509Certificate[] arg0, Ssortingng arg1) throws CertificateException {} public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }}, new java.security.SecureRandom()); return ClientBuilder.newBuilder() .sslContext(sslcontext) .hostnameVerifier((s1, s2) -> true) .build(); } 

J’ai eu le même problème et je ne voulais pas que ce soit défini globalement, donc j’ai utilisé le même code TrustManager et SSLContext que ci-dessus, j’ai juste changé le client pour être créé 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( Ssortingng s, SSLSession sslSession ) { // whatever your matching policy states } } )); Client client = Client.create(config); 

Ce code ne sera exécuté que sur des serveurs de test. Je ne veux donc pas append de nouveaux certificates de confiance chaque fois que nous configurons un nouveau serveur de test.

C’est le type de code qui finira par trouver sa place dans la production (sinon de vous, quelqu’un d’autre qui lit cette question copiera et collera les gestionnaires de confiance non sécurisés qui ont été suggérés dans leurs applications). Il est tellement facile d’oublier de supprimer ce type de code lorsque vous avez une échéance, car cela ne se présente pas comme un problème.

Si vous craignez d’avoir à append de nouveaux certificates chaque fois que vous avez un serveur de test, créez votre propre petite autorité de certificateion, émettez tous les certificates des serveurs de test utilisant cette autorité de certificateion et importez ce certificate dans votre magasin de clés client. (Même si vous ne traitez pas des choses comme la révocation de certificates en ligne dans un environnement local, cela est certainement préférable à l’utilisation d’un gestionnaire de confiance qui laisse passer quoi que ce soit.)

Il existe des outils pour vous aider, par exemple TinyCA ou XCA .

Étant donné que je suis nouveau dans le stackoverflow et que je suis moins réputé pour commenter les réponses des autres, je propose la solution proposé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, Ssortingng authType){} public void checkServerTrusted(X509Certificate[] certs, Ssortingng 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); 

Il suffit d’append le même code avec les importations. Contient également le code non implémenté nécessaire à la compilation. Au début, j’avais du mal à trouver ce qui était importé pour ce code. Ajout du bon package pour le certificate X509. Cela fonctionne avec des essais et des erreurs:

 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, Ssortingng arg1) throws CertificateException { // TODO Auto-generated method stub } public void checkClientTrusted(X509Certificate[] arg0, Ssortingng arg1) throws CertificateException { } public void checkClientTrusted( java.security.cert.X509Certificate[] arg0, Ssortingng arg1) throws java.security.cert.CertificateException { // TODO Auto-generated method stub } public void checkServerTrusted( java.security.cert.X509Certificate[] arg0, Ssortingng 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) { ; } 

Pour quiconque sur Jersey 2.x sans lambda, 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, Ssortingng arg1) throws CertificateException{} public void checkServerTrusted(X509Certificate[] arg0, Ssortingng arg1) throws CertificateException{} public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }}, new java.security.SecureRandom()); HostnameVerifier allowAll = new HostnameVerifier() { @Override public boolean verify(Ssortingng hostname, SSLSession session) { return true; } }; return ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier(allowAll).build(); } 

Testé avec le client de maillot 2.11 sur JRE 1.7 .

Pour Jersey 2. *:

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

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

Pour Jersey 1.X

  TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { public void checkClientTrusted(java.security.cert.X509Certificate[] chain, Ssortingng authType) throws java.security.cert.CertificateException {} public void checkServerTrusted(java.security.cert.X509Certificate[] chain, Ssortingng 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(Ssortingng ssortingng, SSLSession sslSession) { return true; } }); 

travaillé pour moi avec ce code. Peut-être son 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, Ssortingng arg1) throws CertificateException { // TODO Auto-generated method stub } @Override public void checkClientTrusted(X509Certificate[] arg0, Ssortingng 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) { ; }