Vaishakh MR
Vaishakh MR

Reputation: 21

How to override ciphers/protocols programatically on JAX-RS client

I'm facing issue while trying to override ciphers/protocols on JAX-RS client. Jersey framework is used here.

Following is the way client is built.

Client client = ClientBuilder.newBuilder().sslContext(sslContext).hostnameVerifier(hostnameVerifier).build();

I have tried following approaches, but couldn't succeed.

  1. Created Custom SSLSocketFactory, and override ciphers and protocols on createSocket() method of SSL SocketFactory class. Then, HttpsURLConnection.setDefaultSSLSocketFactory(sf). But, its not reflected with this approach.

  2. Tried overriding the sslcontext with help of SslContextFactory & SSLParameters, which also could help.

Could someone help in finding a way to override ciphers/protocols programatically on sslContext of JAX-RS client?

Upvotes: 2

Views: 1062

Answers (1)

Saar peer
Saar peer

Reputation: 847

You can implement an SSLSocketFactory :

public class CustomSSLSocketFactory extends SSLSocketFactory {

    private final SSLSocketFactory sslSocketFactory;

    public CustomSSLSocketFactory(SSLSocketFactory sslSocketFactory) {
        this.sslSocketFactory = sslSocketFactory;
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return sslSocketFactory.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return sslSocketFactory.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket() throws IOException {
        return adjustEnabledCipherSuites((SSLSocket) sslSocketFactory.createSocket());
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
        return adjustEnabledCipherSuites((SSLSocket) sslSocketFactory.createSocket(socket, host, port, autoClose));
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException {
        return adjustEnabledCipherSuites((SSLSocket) sslSocketFactory.createSocket(host, port));
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
        return adjustEnabledCipherSuites((SSLSocket) sslSocketFactory.createSocket(host, port, localHost, localPort));
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        return adjustEnabledCipherSuites((SSLSocket) sslSocketFactory.createSocket(host, port));
    }

    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        return adjustEnabledCipherSuites((SSLSocket) sslSocketFactory.createSocket(address, port, localAddress, localPort));
    }

    private SSLSocket adjustEnabledCipherSuites(SSLSocket sslSocket) {
        sslSocket.setEnabledCipherSuites(new String[]{"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"});
        return sslSocket;
    }
} 

Now you need to configure your client to use a custom ConnectionFactory that uses the above SSLSocketFactory :

ClientConfig clientConfig = new ClientConfig()
CustomSSLSocketFactory sslSocketFactory = new CustomSSLSocketFactory(sslContext.getSocketFactory());

 HttpUrlConnectorProvider.ConnectionFactory factory = url -> {
     HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
     httpsURLConnection.setSSLSocketFactory(sslSocketFactory);
     return httpsURLConnection;
 };
 clientConfig.connectorProvider(new HttpUrlConnectorProvider().connectionFactory(factory));

...

Client client = ClientBuilder.newBuilder().sslContext(sslContext).hostnameVerifier(hostnameVerifier).withConfig(clientConfig).build();

Upvotes: 2

Related Questions