我正在尝试为一个使用SSL的外部HTTP API创建FeignClient。 斗争是 - 如何使用我的逻辑修改默认的Spring FeignClient,在本例中为SSL Connection Factory。所以基本上我想保留Spring自动为FeignClients做的所有好事,比如Hystrix,侦探跟踪等,并让它适用于我的SSL工厂。
欢迎任何建议。
这是我尝试做的事情:
我尝试在ComponentScan之外提供自定义@Configuration:
@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通过注释使用它
@FeignClient(name = "sslClient", configuration = CustomFeignConfiguration.class, url = "https://...")
Where" TrustingSSLSocketFactory"实现类似于this。
现在如果我在Spring应用程序中注入我的客户端,我可以看到" feignBuilder"被叫,它成功加载了我的钥匙。问题是创建的客户端实际上并未使用指定的SSLFactory进行createSocket调用。所以我得到了:
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]
答案 0 :(得分:1)
创建Client
作为自己的@Bean
,而不是构建器的一部分。稍后会调用builder.client(client)
,覆盖您在创建构建器时设置的客户端。
所以
@Bean
public Client feignClient()
{
Client trustSSLSockets = new Client.Default(
TrustingSSLSocketFactory.get("server1"),
new NoopHostnameVerifier());
log.info("feignClient called");
return trustSSLSockets;
}
答案 1 :(得分:0)
我做了这样的事情达到了我的目的-
@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);
}
}