Feign配置HTTPS证书校验忽略的完整方案(保持负载均衡正常)
- 同时处理HTTPS的SSL证书校验问题和Feign框架不支持PATCH请求方式的问题
代码 1. 工具类 SslTrustHelper.java
import javax.net.ssl.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
/**
* SSL证书校验忽略工具类
*/
public class SslTrustHelper {
/**
* 自定义TrustManager实现,接受任意证书
*/
public static final X509TrustManager UNSAFE_TRUST_MANAGER = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] certificates, String authType) {
// 跳过客户端证书校验
}
@Override
public void checkServerTrusted(X509Certificate[] certificates, String authType) {
// 跳过服务端证书校验
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
/**
* 创建忽略证书校验的SSLContext实例
*
* @return 配置完成的SSLContext对象
* @throws NoSuchAlgorithmException 算法不支持异常
* @throws KeyManagementException 密钥管理异常
*/
public static SSLContext createUnsafeSslContext() throws NoSuchAlgorithmException, KeyManagementException {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[]{UNSAFE_TRUST_MANAGER}, new SecureRandom());
return context;
}
/**
* 创建忽略主机名验证的HostnameVerifier
*
* @return 始终返回true的HostnameVerifier
*/
public static HostnameVerifier createPermissiveHostnameVerifier() {
return new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
}
}
代码 2. 配置类 FeignClientConfig.java
import feign.Client;
import feign.okhttp.OkHttpClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
@Slf4j
@Configuration
public class FeignClientConfig {
/**
* 配置FeignClient以支持HTTPS和PATCH请求
*
* @param cachingFactory 负载均衡工厂
* @param clientFactory 客户端工厂
* @return 配置完成的Feign Client
* @throws NoSuchAlgorithmException 算法异常
* @throws KeyStoreException 密钥库异常
* @throws KeyManagementException 密钥管理异常
*/
@Bean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory)
throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
// 关键:必须使用LoadBalancerFeignClient包装,否则负载均衡将失效
// 现象:消费者无法从服务注册中心获取服务提供者的IP地址
// 方案一:使用默认Client(仅解决证书验证问题,不支持PATCH)
// return new LoadBalancerFeignClient(
// new Client.Default(sslContext.getSocketFactory(), new NoopHostnameVerifier()),
// cachingFactory, clientFactory);
// 方案二:使用OkHttpClient(同时解决证书验证和PATCH方法支持)
okhttp3.OkHttpClient okHttpClient = new okhttp3.OkHttpClient.Builder()
.sslSocketFactory(
SslTrustHelper.createUnsafeSslContext().getSocketFactory(),
SslTrustHelper.UNSAFE_TRUST_MANAGER)
.hostnameVerifier(SslTrustHelper.createPermissiveHostnameVerifier())
.build();
return new LoadBalancerFeignClient(
new OkHttpClient(okHttpClient),
cachingFactory,
clientFactory);
}
}
核心要点说明
在使用Feign调用HTTPS接口时,主要面临两个挑战:一是SSL证书校验导致的连接失败,二是Feign原生不支持HTTP的PATCH方法。通过上述配置方案,利用OkHttpClient作为底层HTTP客户端,能够完美解决这两个问题。
需要特别注意的是,在配置FeignClient时,必须使用LoadBalancerFeignClient对底层客户端进行包装。如果直接使用普通的Client实例,将导致服务消费者无法从注册中心获取服务提供者的IP地址,负载均衡机制将完全失效。
该方案在Spring Cloud微服务架构中具有广泛的适用性,特别是在开发测试环境需要跳过证书验证的场景下尤为实用。