SpringBoot: FeignClient with SSL (p12)

谁说我不能喝 提交于 2019-12-01 20:51:57

问题


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]

回答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;
}



回答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);
    }
}


来源:https://stackoverflow.com/questions/40853829/springboot-feignclient-with-ssl-p12

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!