I'm developing a service that can connect REST with Java, and are there any requests I'm making? There is a case that I want to confirm. In such a case, I go through a proxy, but I have investigated how to do it, and I will organize the results. As the Java REST Client, the client part of Jersey, which is also the reference implementation of JAX-RS, is used.
I am always grateful for the wisdom of my predecessors. Basically, I referred to the information on this site. How to proxy with JerseyClient
However, at least the API I'm accessing this time has the following SSL error:
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
Seems to occur, so I will focus on the additional investigation.
pom.xml
<!--But if you just use the Jersey client-->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.25</version>
</dependency>
<!--Furthermore, when using Proxy with Jersey.-->
<dependency>
<groupId>org.glassfish.jersey.connectors</groupId>
<artifactId>jersey-apache-connector</artifactId>
<version>2.25</version>
</dependency>
Access destination is Qiita API
https://qiita.com/api/v2/users/qiita/items?per_page=1&page=4
I will try to target.
curl 'https://qiita.com/api/v2/users/qiita/items' -d 'per_page=1' -d 'page=4' -G
I think that JSON is returned.
Next is Java. First is the pattern that does not pass through the proxy.
We will implement it referring to the following document. Jersey 2.25 User Guide/5. Client API
ClientSamples.java
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
public class ClientSamples {
public static void main(String[] args) {
new ClientSamples().execute();
}
public void execute() {
String target = "https://qiita.com";
String path = "/api/v2/users/qiita/items";
// Client client = createSecureClient();
Client client = createClient();
Response restResponse = client
.target(target)
.path(path)
.queryParam("page", "4")
.queryParam("per_page", "1")
.request(MediaType.APPLICATION_JSON_TYPE)
.get();
System.out.println(restResponse.readEntity(String.class));
}
private Client createClient() {
return ClientBuilder.newClient();
}
}
You should get the same result as with curl.
Please refer to the following page and the site that I mentioned earlier as a reference. How to proxy with JerseyClient Jersey 2.25 User Guide/5.9. Securing a Client
ClientSamples.java
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
public class ClientSamples {
public static void main(String[] args) {
new ClientSamples().execute();
}
public void execute() {
String target = "https://qiita.com";
String path = "/api/v2/users/qiita/items";
Client client = createSecureClient();
// Client client = createClient();
Response restResponse = client
.target(target)
.path(path)
.queryParam("page", "4")
.queryParam("per_page", "1")
.request(MediaType.APPLICATION_JSON_TYPE).get();
System.out.println(restResponse.readEntity(String.class));
}
private Client createSecureClient() {
String proxyHost = "http://127.0.0.1:8080";
ClientConfig config = new ClientConfig();
//Proxy support provider?To
config.connectorProvider(new ApacheConnectorProvider());
config.property(ClientProperties.PROXY_URI, proxyHost);
// config.property(ClientProperties.PROXY_USERNAME, "userName");
// config.property(ClientProperties.PROXY_PASSWORD, "password");
//Generate builder
ClientBuilder b = ClientBuilder.newBuilder().withConfig(config);
return b.build();
}
}
When I run it, I still get a javax.net.ssl.SSLHandshakeException. It looks like you're trying to connect to an untrusted SSL server through a proxy. So, insert the following code to invalidate the SSL certificate verification process and the host name verification process.
ClientSamples.java
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
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.X509TrustManager;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
public class ClientSamples {
public static void main(String[] args) {
new ClientSamples().execute();
}
public void execute() {
String target = "https://qiita.com";
String path = "/api/v2/users/qiita/items";
Client client = createSecureClient();
// Client client = createClient();
Response restResponse = client
.target(target)
.path(path)
.queryParam("page", "4")
.queryParam("per_page", "1")
.request(MediaType.APPLICATION_JSON_TYPE)
.get();
System.out.println(restResponse.readEntity(String.class));
}
private Client createClient() {
return ClientBuilder.newClient();
}
private Client createSecureClient() {
String proxyHost = "http://127.0.0.1:8080";
ClientConfig config = new ClientConfig();
//Proxy support provider?To
config.connectorProvider(new ApacheConnectorProvider());
config.property(ClientProperties.PROXY_URI, proxyHost);
// config.property(ClientProperties.PROXY_USERNAME, "userName");
// config.property(ClientProperties.PROXY_PASSWORD, "password");
SSLContext sslContext = createSSLContext();
HostnameVerifier hostnameVerifier = createHostNameVerifier();
//Generate builder
ClientBuilder b = ClientBuilder.newBuilder().withConfig(config)
.sslContext(sslContext).hostnameVerifier(hostnameVerifier);
return b.build();
}
private SSLContext createSSLContext() {
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null,
new X509TrustManager[] { new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain,String authType) throws CertificateException {}
@Override
public void checkServerTrusted(X509Certificate[] chain,String authType) throws CertificateException {}
@Override
public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];}
} }, new SecureRandom());
// HttpsURLConnection
// .setDefaultSSLSocketFactory(sslContext.getSocketFactory());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
return sslContext;
}
private HostnameVerifier createHostNameVerifier() {
return new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {return true;}
};
}
}
This seems to work. .. It seems that it can handle cases such as putting the Oreore certificate in the test server.
How to proxy with JerseyClient Jersey 2.25 User Guide/5. Client API Jersey 2.25 User Guide/5.9. Securing a Client
Recommended Posts