How to pass a proxy when throwing REST over SSL in Java

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 settings

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>

Building a client

Access destination is Qiita API

https://qiita.com/api/v2/users/qiita/items?per_page=1&page=4

I will try to target.

First with curl.

curl 'https://qiita.com/api/v2/users/qiita/items' -d 'per_page=1' -d 'page=4' -G

I think that JSON is returned.

In Java

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.

Try through a proxy.

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.

Related Links

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

How to pass a proxy when throwing REST over SSL in Java
How to display a web page in Java
How to create a data URI (base64) in Java
How to convert A to a and a to A using AND and OR in Java
How to convert a file to a byte array in Java
Summary of how to use the proxy set in IE when connecting with Java
How to store a string from ArrayList to String in Java (Personal)
How to develop and register a Sota app in Java
How to simulate uploading a post-object form to OSS in Java
How to set up a proxy with authentication in Feign
How to make a Java container
How to learn JAVA in 7 days
How to batch initialize arrays in Java that I didn't know when I was a beginner
[Java] How to create a folder
How to use classes in Java?
How to name variables in Java
How to make a Java array
How to concatenate strings in java
How to automatically operate a screen created in Java on Windows
How to solve the unknown error when using slf4j in Java
How to make a Java calendar Summary
When seeking multiple in a Java array
How to implement date calculation in Java
How to implement Kalman filter in Java
Multilingual Locale in Java How to use Locale
How to insert a video in Rails
How to do base conversion in Java
[Introduction to Java] How to write a Java program
How to make a Discord bot (Java)
How to implement coding conventions in Java
How to embed Janus Graph in Java
How to print a Java Word document
How to get the date in java
How to publish a library in jCenter
How to test a private method in Java and partially mock that method
[IntelliJ IDEA] How to automatically add final when saving a Java file
[Personal memo] How to interact with a random number generator in Java
How to find the total number of pages when paging in Java
How to get the absolute path of a directory running in Java
[Java] [For beginners] How to insert elements directly in a 2D array
How to track when a bucket managed by scoop changes (mainly Java)
How to reference a column when overriding the column name method in ActiveRecord
How to redirect to http-> https when SSL is enabled in Rails × Heroku environment
[Rails] How to write when making a subquery
Try to create a bulletin board in Java
How to fix a crash when deleting Realm data in Swift UI List
How to get Class from Element in Java
A note when you want Tuple in Java
I wanted to make (a == 1 && a == 2 && a == 3) true in Java
How to convert a solidity contract to a Java contract class
How to run a djUnit task in Ant
How to add a classpath in Spring Boot
How to create a theme in Liferay 7 / DXP
How to hide null fields in response in Java
How to ZIP a JAVA CSV file and manage it in a Byte array
How to implement a like feature in Rails
How to easily create a pull-down in Rails
How to implement optimistic locking in REST API
[Java] How to substitute Model Mapper in Jackson
How to solve an Expression Problem in Java
How to make a follow function in Rails