前两天需要通过springboot-feign来调用一个https的外部服务接口,因此要实现feign-client的SSL设置。
feign执行http请求通常会调用 feign . Client 接口的实现。这个接口的默认实现类 Default 提供了添加SSL配置的构造器:
public static class Default implements Client { private final SSLSocketFactory sslContextFactory; private final HostnameVerifier hostnameVerifier; /** * Null parameters imply platform defaults. */ public Default(SSLSocketFactory sslContextFactory, HostnameVerifier hostnameVerifier) { this.sslContextFactory = sslContextFactory; this.hostnameVerifier = hostnameVerifier; } ... }
简单介绍下构造器参数中用到的SSL相关的接口:
默认使用的Client实例的两个构造参数的值都是null。我们需要在配置类中创建使用SSL的Client实例,这里参考了默认的配置类 FeignClientsConfiguration :
@Configuration public class SSLFeignClientConfig { @Bean @Scope("prototype") @ConditionalOnMissingBean public Feign.Builder feignBuilder(Client client) { return Feign.builder().client(client); } @Bean public Client client() { try { SSLContext context = new SSLContextBuilder().loadTrustMaterial(null, (chain, authType) -> true).build(); return new Client.Default(context.getSocketFactory(), new NoopHostnameVerifier()); } catch (Exception e) { return new Client.Default(null, null); } } }
代码中使用了 SSLContext 的getSocketFactory方法来创建 SSLSocketFactory 对象。在创建 SSLContext 对象时,通过 ( chain , authType ) -> true 指定了SSL信任策略,即:不做任何处理,信任全部请求。
另一个 HostnameVerifier 类型的参数使用了一个实现类 NoopHostnameVerifier 的实例,作用是关闭主机名验证功能,并且永远不会抛出SSLException。
最后将配置添加到FeignClient注解上即可:
@FeignClient(name = "zhyeaApiService", url = "${zhyea-url}", configuration = {FeignClientsConfiguration.class, SSLFeignClientConfig.class})
如代码中所示可以为configuration项一次指定多个配置类。这里的第一个配置类是spring默认提供的配置类。
就这样了。