Ignore self-signed ssl cert using Jersey Client

JavaSslSsl CertificateJersey

Java Problem Overview


I'm using the Jersey Client library to run tests against a rest service running on jboss. I have https set up fine on the server (running on localhost), using a self signed cert.

However whenever I run my tests with the https url I get the following error:

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.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

I know this is because my self signed cert is not in the java keystore. Is there any way I can make the Client not check the validity of the ssl cert and just use it regardless?

This code will only ever be run against test servers so I don't want to go to the hassle of adding new trusted certs each time we set up a new test server.

Here's the code which is making the call:

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

Any help would be greatly appreciated.

Java Solutions


Solution 1 - Java

After some searching and trawling through some old stackoverflow questions I've found a solution in a previously asked SO question:

Here's the code that I ended up using.

// 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) {
    ;
}

Solution 2 - Java

For Jersey 2.* (Tested on 2.7) and 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();
}

Solution 3 - Java

I had the same problem adn did not want this to be set globally, so I used the same TrustManager and SSLContext code as above, I just changed the Client to be created with special properties

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

Solution 4 - Java

Since I am new to stackoverflow and have lesser reputation to comment on others' answers, I am putting the solution suggested by Chris Salij with some modification which worked for me.

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

Solution 5 - Java

> This code will only ever be run against test servers so I don't want > to go to the hassle of adding new trusted certs each time we set up a > new test server.

This is the kind of code that will eventually find its way in production (if not from you, someone else who's reading this question will copy and paste the insecure trust managers that have been suggested into their applications). It's just so easy to forget to remove this sort of code when you have a deadline, since it doesn't show up as a problem.

If you're worried about having to add new certificates every time you have a test server, create your own little CA, issue all the certificates for the test servers using that CA and import this CA certificate into your client trust store. (Even if you don't deal with things like online certificate revocation in a local environment, this is certainly better than using a trust manager that lets anything through.)

There are tools to help you do this, for example TinyCA or XCA.

Solution 6 - Java

For anyone on Jersey 2.x without lambdas, use this:

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();
}

Tested with jersey-client 2.11 on JRE 1.7.

Solution 7 - Java

Just adding the same code with the imports. Also contains the unimplemented code that is needed for compilation. I initially had trouble finding out what was imported for this code. Also adding the right package for the X509Certificate. Got this working with trial and error:

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) {
	 ;
 }

Solution 8 - Java

For 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

Solution 9 - Java

I noticed that when using the Apache http client configuration with a pooling manager, the accepted answer doesn't work.

In this case it appears that the ClientConfig.sslContext and ClientConfig.hostnameVerifier setters are silently ignored. So if you are using connection pooling with the apache client http client config, you should be able to use the following code to get ssl verification to be ignored:

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

Solution 10 - Java

For 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;
		}
	});

Solution 11 - Java

Okay, I'd like to just add my class only because there might be some dev out there in the future that wants to connect to a Netbackup server (or something similar) and do stuff from Java while ignoring the SSL cert. This worked for me and we use windows active directory for auth to the Netbackup server.

public static void main(String[] args) throws Exception {
    SSLContext sslcontext = null;
    try {
        sslcontext = SSLContext.getInstance("TLS");
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
    }
    try {
        sslcontext.init(null, new TrustManager[]{new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
            @Override
            public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
                //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
            }

            @Override
            public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
                //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
            }
        }}, new java.security.SecureRandom());
    } catch (KeyManagementException ex) {
        Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
    }
    //HttpAuthenticationFeature feature = HttpAuthenticationFeature.basicBuilder().credentials(username, password).build();
    ClientConfig clientConfig = new ClientConfig();
    //clientConfig.register(feature);
    Client client = ClientBuilder.newBuilder().withConfig(clientConfig)
            .sslContext(sslcontext)
            .hostnameVerifier((s1, s2) -> true)
            .build();

    //String the_url = "https://the_server:1556/netbackup/security/cacert";
    String the_token;
    {
        String the_url = "https://the_server:1556/netbackup/login";
        WebTarget webTarget = client.target(the_url);

        Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
        String jsonString = new JSONObject()
                .put("domainType", "NT")
                .put("domainName", "XX")
                .put("userName", "the username")
                .put("password", "the password").toString();
        System.out.println(jsonString);
        Response response = invocationBuilder.post(Entity.json(jsonString));
        String data = response.readEntity(String.class);
        JSONObject jo = new JSONObject(data);
        the_token = jo.getString("token");
        System.out.println("token is:" + the_token);

    }
    {
        String the_url = "https://the_server:1556/netbackup/admin/jobs/1122012"; //job id 1122012 is an example
        WebTarget webTarget = client.target(the_url);
        Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON).header(HttpHeaders.AUTHORIZATION, the_token).header(HttpHeaders.ACCEPT, "application/vnd.netbackup+json;version=1.0");
        Response response = invocationBuilder.get();
        System.out.println("response status:" + response.getStatus());
        String data = response.readEntity(String.class);
        //JSONObject jo = new JSONObject(data);
        System.out.println(data);
    }
}

I know it can be considered off-topic, but I bet the dev that tries to connect to a Netbackup server will probably end up here. By the way many thanks to all the answers in this question! The spec I'm talking about is here and their code samples are (currently) missing a Java example.

***This is of course unsafe since we ignore the cert!

Solution 12 - Java

worked for me with this code. May be its for 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) {
	    ;
	}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChris SalijView Question on Stackoverflow
Solution 1 - JavaChris SalijView Answer on Stackoverflow
Solution 2 - JavaeitanView Answer on Stackoverflow
Solution 3 - JavaRansom BriggsView Answer on Stackoverflow
Solution 4 - JavaMukeshView Answer on Stackoverflow
Solution 5 - JavaBrunoView Answer on Stackoverflow
Solution 6 - JavaomniView Answer on Stackoverflow
Solution 7 - Javaprakash krishnanView Answer on Stackoverflow
Solution 8 - JavaMarcelo C.View Answer on Stackoverflow
Solution 9 - JavaNicholas DiPiazzaView Answer on Stackoverflow
Solution 10 - JavagrepView Answer on Stackoverflow
Solution 11 - JavaxtsolerView Answer on Stackoverflow
Solution 12 - JavaTapasView Answer on Stackoverflow