SpringBoot: FeignClient with SSL (p12)

14,844

Solution 1

Create the Client as it's own @Bean rather than part of the builder. builder.client(client) gets called later on, overriding the client you set while creating the builder.

So

@Bean
public Client feignClient()
{
    Client trustSSLSockets = new Client.Default(
            TrustingSSLSocketFactory.get("server1"),
            new NoopHostnameVerifier());

    log.info("feignClient called");
    return trustSSLSockets;
}

Solution 2

I did something like this which served my purpose-

@Bean
public Client feignClient()
{
    Client trustSSLSockets = new Client.Default(getSSLSocketFactory(), new NoopHostnameVerifier());
    log.info("feignClient called"); 
    return trustSSLSockets;
}


private SSLSocketFactory getSSLSocketFactory() {
    try {
    TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
        @Override
        public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            //Do your validations
            return true;
        }
        };

        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
        return sslContext.getSocketFactory();
    } catch (Exception exception) {
        throw new RuntimeException(exception);
    }
}
Share:
14,844
Val
Author by

Val

Updated on June 04, 2022

Comments

  • Val
    Val almost 2 years

    I'm trying to create a FeignClient for one external HTTP API which uses SSL. The struggle is - how to modify default Spring FeignClient with my logic, in this case SSL Connection Factory. So basically I wanna keep all the good things Spring automatically does for the FeignClients, like Hystrix, Sleuth tracing, etc and make it work with my SSL factory.

    Will appreciate any suggestions.


    Here is what I tried to do:

    I've tried to provide a custom @Configuration outside of ComponentScan:

    @Configuration
    public class CustomFeignConfiguration
    {
        @Bean
        public Feign.Builder feignBuilder()
        {
            Client trustSSLSockets = new Client.Default(
                    TrustingSSLSocketFactory.get("server1"),
                    new NoopHostnameVerifier());
    
            log.info("feignBuilder called");
            return Feign.builder().client(trustSSLSockets);
        }
    ...
    }
    

    Made FeignClient use it through annotation

        @FeignClient(name = "sslClient", configuration = CustomFeignConfiguration.class, url = "https://...")
    

    Where "TrustingSSLSocketFactory" is implemented similar to this.

    Now if I inject my client in a Spring application, I can see that "feignBuilder" was called and it successfully loaded my keys. The problem is that the created client doesn't actually use the specified SSLFactory for createSocket calls. So I get:

    Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) ~[na:1.8.0_72]
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:154) ~[na:1.8.0_72]
        at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023) ~[na:1.8.0_72]
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125) ~[na:1.8.0_72]
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) ~[na:1.8.0_72]
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403) ~[na:1.8.0_72]
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387) ~[na:1.8.0_72]
        at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559) ~[na:1.8.0_72]
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185) ~[na:1.8.0_72]
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1513) ~[na:1.8.0_72]
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441) ~[na:1.8.0_72]
        at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480) ~[na:1.8.0_72]
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338) ~[na:1.8.0_72]
        at feign.Client$Default.convertResponse(Client.java:152) ~[feign-core-9.3.1.jar:na]