JDK对SSL报错的处理方案
原创大约 2 分钟
背景介绍
有一个外部系统需要以API方式调用,但是调用的时候报SSL错误,需要处理SSL问题。
方案1 - 导入证书到jre证书库
操作步骤
<domain_name> 是域名地址
# 下载证书
echo -n | openssl s_client -connect <domain_name>:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > <domain_name>.crt
# 导入证书
keytool -import -noprompt -keystore %JAVA_HOME%/jre/lib/security/cacerts -storepass changeit -alias xxxxcert -file <domain_name>.crt
# 验证证书是否导入成功
keytool -list -keystore %JAVA_HOME%/jre/lib/security/cacerts -storepass changeit
方案2- 代码兼容,对SSL证书进行忽略
当使用HttpClient时,你可以通过自定义SSL上下文来解决PKIX路径构建失败的问题。下面核心代码演示:
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustAllStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
public class HttpClientWithCustomSSLContext {
public static void main(String[] args) throws Exception {
// Create a custom SSL context that trusts all certificates
SSLContextBuilder sslContextBuilder = SSLContextBuilder.create();
sslContextBuilder.loadTrustMaterial(TrustAllStrategy.INSTANCE);
// Disable hostname verification
HttpClient httpClient = HttpClients.custom()
.setSSLContext(sslContextBuilder.build())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
// Make a request with the custom HttpClient
HttpGet request = new HttpGet("https://example.com");
HttpResponse response = httpClient.execute(request);
// Process response as needed
}
}
某SDK已经封装了HttpClient,修改代码如下 其中
.setConnectionManager(connectionManager)
影响SSL的验证 , 解决了PKIX path building failed错误
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", new SSLConnectionSocketFactory(
SSLContextBuilder.create().loadTrustMaterial(TrustAllStrategy.INSTANCE).build(),
NoopHostnameVerifier.INSTANCE))
.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
int maxCon = configuration.getMaxConnections();
int maxConPerRoute = configuration.getMaxConPerRoute();
connectionManager.setMaxTotal(maxCon);
connectionManager.setDefaultMaxPerRoute(maxConPerRoute);
ConnectionKeepAliveStrategy strategy;
if (connectionKeepAliveStrategy != null) {
strategy = connectionKeepAliveStrategy;
} else {
strategy = getConnectionKeepAliveStrategy();
}
HttpClient httpClient;
httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setKeepAliveStrategy(strategy)
.setRetryHandler(httpRequestRetryHandler)
.setDefaultRequestConfig(RequestConfig.custom().setStaleConnectionCheckEnabled(true).build())
.setProxy(proxy)
.build();
上述代码原来的代码为:
该代码存在PKIX path building failed错误
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
int maxCon = configuration.getMaxConnections();
int maxConPerRoute = configuration.getMaxConPerRoute();
connectionManager.setMaxTotal(maxCon);
connectionManager.setDefaultMaxPerRoute(maxConPerRoute);
ConnectionKeepAliveStrategy strategy;
if (connectionKeepAliveStrategy != null) {
strategy = connectionKeepAliveStrategy;
} else {
strategy = getConnectionKeepAliveStrategy();
}
HttpClient httpClient;
httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setKeepAliveStrategy(strategy)
.setRetryHandler(httpRequestRetryHandler)
.setDefaultRequestConfig(RequestConfig.custom().setStaleConnectionCheckEnabled(true).build())
.setProxy(proxy)
.build();