Multiple-thread access by Jersey client 2.25.1 with HTTPS(Certificate) - java

I meet a problem while using "javax.ws.rs.client.Client(Jersey client 2.25.1)" to send https request in multiple-thread context.
1) First I create a client like following:
Client client = ClientBuilder.newBuilder().sslContext(createSSLContext()).build();
private static SSLContext createSSLContext() throws Exception {
SSLContext sslcontext = SSLContext.getInstance(TLS);
KeyManagerFactory kmf =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
try (InputStream keyStoreSteam = new FileInputStream(keystoreFile)) {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(keyStoreSteam, keystorePwd.toCharArray());
kmf.init(ks, keystorePwd.toCharArray());
}
try (InputStream trustStoreSteam = new FileInputStream(trustStoreFile)) {
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(trustStoreSteam, trustStorePwd.toCharArray());
tmf.init(trustStore);
sslcontext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new java.security.SecureRandom());
}
return sslcontext;
}
2) I'm using the "client" to send https request like following:
for(int i = 0; i < 3; i++){
public void run(){
while(true){
Builder request = client.target(url).request(theString);
Request request = request.get();
// other stuffs ...
Thread.current.sleep(5000);
}
}
}).start();
3) An Exception throws out in request.get(). Notice that there are 3 threads of invocation for request.get(), but only one thread successfully gets the response, and other 2 threads get exceptions like the following:
javax.ws.rs.ProcessingException: 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 org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:287)
at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:252)
at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:684)
at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:681)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:681)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:411)
at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:311)
at com.mycode.RequestSender.send(RequestSender.java:37)
at java.lang.Thread.run(Thread.java:745)
Caused by: 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 sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1514)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1546)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:399)
at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:285)
... 15 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496)
... 30 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 36 more
It seems like 3 threads try to load the certification when they send request via https, but only 1 thread successes, the other 2 threads cannot find the valid certification path.
But after one request sends successfully, in the next loop after sleeping, all the 3 threads can send request successfully. So the exception only happens in first sending request in multiple-thread context.
So is this a bug in Jersey client or I use it incorrectly ?

This seems like a bug in Jersey - specifically all latest version (up until 26-b09).
Please see - https://github.com/jersey/jersey/issues/3293
Downgrading to version 2.21.1 resolved this issue for me..

Related

How to connect to a URL without certification problems?

Introduction
I want to be able to retrieve the source page from a website to work on the data. Some webs let me connect to them but the are some which throws at me unable to find valid certification path to requested target
I want to mention that I do not own the website which I am scraping data from* (as some of the solutions I have read so far mentions server owning stuff)*
Moreover, I am still learning and I have some questions, do not be too technical I just want to have this problem sorted out.
Problem
Java doesn't seem to trust the website so throws me the Exception below. I have read some answers here but nothing worked so far.
What I have done so far
I imported the website's certificate needed as:
keytool -import -alias virto -file /path to crt/ -keystore virtocert
Then restarted PC but still getting this Exception error. When I run my code.
Exception in thread "main" 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 sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1937)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1478)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1050)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1512)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1440)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at HttpsClientUtil.main(HttpsClientUtil.java:23)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1460)
... 13 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:145)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 19 more
C:\Users\Jonathan\Desktop\Java\WebScraper_03\WebScraper\nbproject\build-impl.xml:1339: The following error occurred while executing this line:
C:\Users\Jonathan\Desktop\Java\WebScraper_03\WebScraper\nbproject\build-impl.xml:980: Java returned: 1
Code
public static void main(String[] args) throws Exception {
String httpsURL = "https://virtonomics.com/";
String FILENAME = "c:\\temp\\filename.html";
BufferedWriter bw = new BufferedWriter(new FileWriter(FILENAME));
URL myurl = new URL(httpsURL);
HttpsURLConnection con = (HttpsURLConnection) myurl.openConnection();
con.setRequestProperty ( "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0" );
InputStream ins = con.getInputStream();
InputStreamReader isr = new InputStreamReader(ins, "Windows-1252");
BufferedReader in = new BufferedReader(isr);
String inputLine;
// Write each line into the file
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
bw.write(inputLine);
}
in.close();
bw.close();
}
What else do I need to do in order to sort out this problem?
Thanks for the interest in this question.
You could either set up your own keystore and have the certs validated or you could choose to ignore the certs completely.
You can have a look at this post for the various options: Ignore SSL Certificate Errors with Java

How to verify Firebase id token

I was following this https://firebase.google.com/docs/auth/admin/verify-id-tokens to retrieve the idToken in client and verify it on server.
On server side, I use the following Java code to initialize the SDK and verify the token:
String json = // JSON generated from Firebase service account;
ByteArrayInputStream serviceAccount =
new ByteArrayInputStream(json.getBytes(Charsets.UTF_8));
FirebaseOptions options =
new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl() // My database url
.build();
FirebaseApp defaultApp = FirebaseApp.initializeApp(options);
FirebaseAuth defaultAuth = FirebaseAuth.getInstance(defaultApp);
try {
FirebaseToken firebaseToken = Tasks.await(
defaultAuth.verifyIdToken(tokenFromClient));
System.out.println("token email " + firebaseToken.getEmail());
System.out.println("Successfully verify token");
} catch (Exception e) {
System.out.println("token verify error " + e);
}
I got this error
java.util.concurrent.ExecutionException: com.google.firebase.auth.FirebaseAuthException: Error while verifying token signature.
There is deep stack trace trace from the SDK API:
Caused by: com.google.firebase.auth.FirebaseAuthException: Error while verifying token signature.
at com.google.firebase.auth.internal.FirebaseTokenVerifier.verifyTokenAndSignature(FirebaseTokenVerifier.java:152)
at com.google.firebase.auth.FirebaseAuth$2.call(FirebaseAuth.java:223)
at com.google.firebase.auth.FirebaseAuth$2.call(FirebaseAuth.java:211)
at com.google.firebase.tasks.Tasks$1.run(Tasks.java:82)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at com.google.apphosting.runtime.ApiProxyImpl$CurrentRequestThreadFactory$1$1.run(ApiProxyImpl.java:1233)
at java.security.AccessController.doPrivileged(Native Method)
at com.google.apphosting.runtime.ApiProxyImpl$CurrentRequestThreadFactory$1.run(ApiProxyImpl.java:1227)
at java.lang.Thread.run(Thread.java:745)
at com.google.apphosting.runtime.ApiProxyImpl$CurrentRequestThread.run(ApiProxyImpl.java:1194)
Caused by: 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 sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1953)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:220)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1379)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1407)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:104)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:981)
at com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager.refresh(GooglePublicKeysManager.java:172)
at com.google.api.client.googleapis.auth.oauth2.GooglePublicKeysManager.getPublicKeys(GooglePublicKeysManager.java:140)
at com.google.firebase.auth.internal.FirebaseTokenVerifier.verifySignature(FirebaseTokenVerifier.java:174)
at com.google.firebase.auth.internal.FirebaseTokenVerifier.verifyTokenAndSignature(FirebaseTokenVerifier.java:146)
... 10 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1473)
... 26 more
In client, I set force refresh to true when get the id token, so I supposed the id token is not expired yet.
Any help is appreciated.
The root cause was the wrong certificate. Our server is built on App Engine, but we replaced the certificate for project needs. After the certificate issue is fixed, the token verification is successful.

Soap on HTTPS Apache CFX with user certificate authentication not working

We have a server running on Tomcat. This server connects to several third part services.
I developed and tested the connection to a SOAP service. This service requires the client to identify using a certificate. The first version set the properties:
javax.net.ssl.trustStore
javax.net.ssl.trustStorePassword
javax.net.ssl.keyStore
javax.net.ssl.keyStorePassword
javax.net.ssl.keyStoreType
My code worked when tested alone, but when my code was integrated to our server, it messed up the connection to other third part servers. Looking for a solution to this problem, I found Apache CFX. I noted that this library has an API to set the certificates without the need to change global properties. We donĀ“t use Spring and I would like to configure by code, but I am getting exceptions.
Code
public NotaFiscalServiceSoap getNotaFiscalServiceSoap() throws IOException, GeneralSecurityException {
if(notaFiscalServiceSoap==null){
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean() ;
factory.setWsdlURL(municipio.getUrlWsdl().toString());
factory.setServiceClass(NotaFiscalServiceSoap.class);
factory.setServiceName(Q_NAME);
factory.setConduitSelector(getConduitSelector());
notaFiscalServiceSoap = factory.create(NotaFiscalServiceSoap.class);
}
return notaFiscalServiceSoap;
}
private ConduitSelector getConduitSelector() throws IOException, GeneralSecurityException {
ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.setTargetNamespace(NAMESPACE);
EndpointInfo endpointInfo = new EndpointInfo();
endpointInfo.setService(serviceInfo);
endpointInfo.setName(Q_NAME);
endpointInfo.setAddress(municipio.getUrlWsdl().toString());
URLConnectionHTTPConduit conduit = new URLConnectionHTTPConduit(null, endpointInfo);
conduit.setTlsClientParameters(getTLSClientParameters());
ConduitSelector selector = new UpfrontConduitSelector(conduit);
return selector;
}
private TLSClientParameters getTLSClientParameters() throws GeneralSecurityException, IOException{
KeyStoreType trustKeyStore = new KeyStoreType();
trustKeyStore.setFile(pathCertWsdl);
trustKeyStore.setPassword(passCertWsdl);
trustKeyStore.setType("jks");
TrustManagersType trustManagerType = new TrustManagersType();
trustManagerType.setKeyStore(trustKeyStore);
KeyStoreType keyStoreType = new KeyStoreType();
keyStoreType.setFile(pathCertA1);
keyStoreType.setPassword(passCertA1);
keyStoreType.setType("pkcs12");
KeyManagersType keyManagerType = new KeyManagersType();
keyManagerType.setKeyStore(keyStoreType);
keyManagerType.setKeyPassword(passCertA1);
TLSClientParametersType clientParametersType = new TLSClientParametersType();
clientParametersType.setTrustManagers(trustManagerType);
clientParametersType.setKeyManagers(keyManagerType);
clientParametersType.setUseHttpsURLConnectionDefaultHostnameVerifier(true);
clientParametersType.setUseHttpsURLConnectionDefaultSslSocketFactory(true);
return TLSClientParametersConfig.createTLSClientParametersFromType(clientParametersType);
}
Exception
java.security.UnrecoverableKeyException: Password must not be null
at sun.security.provider.JavaKeyStore.engineGetKey(JavaKeyStore.java:132)
at sun.security.provider.JavaKeyStore$JKS.engineGetKey(JavaKeyStore.java:56)
at sun.security.provider.KeyStoreDelegator.engineGetKey(KeyStoreDelegator.java:96)
...
org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:87)
at org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean.buildServiceFromWSDL(ReflectionServiceFactoryBean.java:394)
...
Caused by: javax.wsdl.WSDLException: WSDLException: faultCode=PARSER_ERROR: Problem parsing 'https://issonline.vilavelha.es.gov.br/SistemaIss/WebService/NotaFiscalService.asmx?WSDL'.: 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.ibm.wsdl.xml.WSDLReaderImpl.getDocument(WSDLReaderImpl.java:2198)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(WSDLReaderImpl.java:2390)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(WSDLReaderImpl.java:2422)
...
Caused by: 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 sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
...
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
...
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
...
I found the solution to my problem.
I used this URL as reference: http://www.programcreek.com/java-api-examples/index.php?source_dir=support-examples-master/jaxws/cxfSsl.war/WEB-INF/classes/com/redhat/gss/jaxws/TestClient.java
I changed the way the soap service object was created. That way I could get the HTTPConduit and configure it, instead of having to create many auxiliary objects (probably I made a few mistakes here).
I created the keystores instead of configuring the certificates.

netty 4 client ssl configuration to request all https sites

I have some web crawler based on netty (4.1b7) where I massively request different sites both http and https ones and I'm trying to configure netty client to deal with https sites with different authentication settings.
When I have a simple netty configuration w/o own certificates:
SslContext sslCtx = SslContextBuilder.forClient().build();
SSLEngine sslEngine = sslCtx.newEngine(ch.alloc(), host, port);
p.addLast("ssl", new SslHandler(sslEngine));
Approx half of https sites are requested OK but others failed as:
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1728)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:304)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1506)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker$1.run(Handshaker.java:919)
at sun.security.ssl.Handshaker$1.run(Handshaker.java:916)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1369)
at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1164)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1067)
... 19 moreCaused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:281)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:136)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1493)
... 27 more Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:146)
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 33 more
or:
Caused by: javax.net.ssl.SSLException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1666)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1634)
at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1800)
at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:1083)
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:907)
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1138)
When I tried to generate own local certificates and set them as:
System.setProperty("javax.net.ssl.trustStore", "/etc/ssl/my/cacerts.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
System.setProperty("javax.net.ssl.keyStore", "/etc/ssl/my/keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "changeit");
then all https sites failed with errors like:
Caused by: java.security.cert.CertificateException: found no certificates: /etc/ssl/my/cacerts.jks
at io.netty.handler.ssl.PemReader.readCertificates(PemReader.java:83) ~[netty-all-4.1.0.Beta7.jar:4.1.0.Beta7]
at io.netty.handler.ssl.SslContext.toX509Certificates(SslContext.java:967)
....
Caused by: java.security.KeyException: found no private key: /etc/ssl/my/keystore.jks
at io.netty.handler.ssl.PemReader.readPrivateKey(PemReader.java:99) ~[netty-all-4.1.0.Beta7.jar:4.1.0.Beta7]
at io.netty.handler.ssl.SslContext.toPrivateKey(SslContext.java:923)
Also I tried advises from that SO, but with no luck yet.
What's wrong or can anybody give some kind of step by step guide for configuring netty 4+ client to deal with https sites with all possible auth settings.
Finally I solved issue by hacking TrustManager in code (found this technique on SO):
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}};
// Ignore differences between given hostname and certificate hostname
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);
...
final SSLEngine sslEngine = sc.createSSLEngine(host, port);
sslEngine.setUseClientMode(true);
sslEngine.setNeedClientAuth(false);
p.addLast("ssl", new SslHandler(sslEngine));
Now all https sites which are OK in browser (chrome doesn't show warning at least) - are read by Netty.
try buidling the sslCtx like following
SslContext sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
And add to the pipeline p.addLast(sslCtx.newHandler(ch.alloc()));

How to do a POST call to secure site with restlet that is working fine with curl POST

My curl command is working fine:
curl -u "myusername":"mypassword" -X POST -H "Content-Type: application/json" -d '{
"data": [
{
"val": 867.8,
"date": "2014-06-18T09:56:21+00:00"
},
{
"val": 98.5432,
"date": "2014-06-18T09:58:21+00:00"
}
],
"user_id": "786733",
"pulse_id": "1",
}' https://www.myweb.com/Test/requests
Note that the connection is https i.e. it is using SSL and I didn't mentioned any certificate/keystore/truststore to be given.
However my java code is not working no matter if I add trustore code or not.
My code is working fine if I give the URL locally i.e. localhost.
I am using RESTLET POST call.
For example: http://localhost:8085/Test/requests
But doesn't works if I replace the URL to be https with remote host.
For example: https://www.myweb.com/Test/requests
The following is by just mentioning the remote URL:
Caused by: 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 sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1884)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1439)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:209)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:878)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:814)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
at org.restlet.engine.connector.HttpUrlConnectionCall.sendRequest(HttpUrlConnectionCall.java:356)
at org.restlet.engine.adapter.ClientAdapter.commit(ClientAdapter.java:105)
at org.restlet.engine.adapter.HttpClientHelper.handle(HttpClientHelper.java:119)
at org.restlet.Client.handle(Client.java:153)
at org.restlet.routing.Filter.doHandle(Filter.java:150)
at org.restlet.routing.Filter.handle(Filter.java:197)
at org.restlet.resource.ClientResource.handle(ClientResource.java:1092)
at org.restlet.resource.ClientResource.handleOutbound(ClientResource.java:1176)
at org.restlet.resource.ClientResource.handle(ClientResource.java:1047)
... 6 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:385)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1421)
... 25 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
Code:
Client side:
String json = gson.toJson(obj);
ClientResource clientResource =
new ClientResource("https://www.myweb.com/Test/requests");
StringRepresentation rep = new StringRepresentation(json);
clientResource.post(rep.getText());
Server side:
Main.java -
Component component = new Component();
component.getServers().add(Protocol.HTTPS, port);
component.getDefaultHost().attach("/www.myweb.com"),new UserApplication());
component.start();
UserApplication.java -
#Override
public Restlet createInboundRoot() {
String routerName = "/Test";
String aPIName = "/requests";
Router rootRouter2 = new Router(getContext());
Router getAdapterRouter = new Router(getContext());
getEnerNocAdapterRouter.attach(aPIName, PersistentData.class);
rootRouter2.attach(routerName, getAdapterRouter);
return rootRouter2;
}
PersistentData.java-
#Post
public void receiveData(Representation rep) throws ResourceException{
LOGGER.info("Server received Data");
try {
LOGGER.info("Server Data: "+rep.getText().toString());
} catch (IOException e) {
LOGGER.error("Error in receiving data", e);
}
}
If the certificate is a self-signed one (it seems to be the case), you should have a look at this page within the Restlet documentation: http://restlet.com/technical-resources/restlet-framework/guide/2.3/core/security/https
Hope it will help you,
Thierry

Categories