Java11+SpringBoot2.1.6调用HTTPS POST报SSL连接重置如何解决
问题排查与解决方案
1. 优先修复代码逻辑顺序错误
你当前processURL方法的执行顺序存在严重逻辑问题:
// 这里先给未初始化的httpPost(大概率是类成员变量)设置请求体 httpPost.setEntity(entity); HttpClient httpClient = getAPIBasicAuthDefaultHttpClient(); try { // 这里才实例化局部httpPost对象,最终发出的请求完全没有携带请求体 HttpPost httpPost = buildPostWithHeaders(userId, emailId); HttpResponse response = httpClient.execute(httpPost); // 后续逻辑 }
空请求发送到服务端后会被判定为非法请求直接断开连接,就是你遇到的Connection reset报错的核心原因,修正执行顺序即可:
public void processURL(UserInput userInput, String userId, String emailId) { String requestJson = helper.marshallObjectToJson(userInput); StringEntity entity = new StringEntity(requestJson, "UTF8"); entity.setContentType(new BasicHeader("Content-Type", "application/json")); HttpClient httpClient = getAPIBasicAuthDefaultHttpClient(); try { // 先实例化HttpPost对象 HttpPost httpPost = buildPostWithHeaders(userId, emailId); // 再给该对象设置请求体 httpPost.setEntity(entity); HttpResponse response = httpClient.execute(httpPost); respStatus = response.getStatusLine().getStatusCode(); if (HttpStatus.SC_CREATED == respStatus) { logger.info("success"); } else { logger.error("Failure"); } } catch (Exception e) { e.printStackTrace(); } }
2. 修复逻辑后仍报错的SSL相关排查方案
如果调整顺序后还是出现连接重置,按以下步骤排查:
- TLS版本适配:Java 11默认禁用了TLS 1.0、TLS 1.1协议,如果目标接口仅支持低版本TLS,需要在HttpClient构造时指定支持的TLS版本,测试阶段可以临时配置信任所有证书:
public HttpClient getAPIBasicAuthDefaultHttpClient() throws NoSuchAlgorithmException, KeyManagementException { CredentialsProvider provider = new BasicCredentialsProvider(); UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(user, password); provider.setCredentials(AuthScope.ANY, credentials); // 配置支持所有TLS版本的SSL上下文 SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {} @Override public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {} @Override public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];} }}, new SecureRandom()); return HttpClientBuilder.create() .setDefaultCredentialsProvider(provider) .setSSLContext(sslContext) // 测试用跳过主机名校验,生产环境建议根据实际情况配置 .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) .build(); }
- 证书信任问题:如果目标接口使用自签名证书,需要把证书导入到服务端JDK的信任库中,默认路径为
$JAVA_HOME/lib/security/cacerts,默认密码为changeit。 - 网络代理问题:如果服务端部署在需要走代理的环境,Rest客户端工具配置了代理但JVM没有配置代理也会导致连接失败,在JVM启动参数中添加对应代理配置即可:
-Dhttp.proxyHost=代理地址 -Dhttp.proxyPort=代理端口 -Dhttps.proxyHost=代理地址 -Dhttps.proxyPort=代理端口
- 超时配置:HttpClient默认没有设置Socket超时,网络链路不稳定也可能触发连接重置,构造HttpClient时添加超时配置:
RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(5000) .setSocketTimeout(30000) .build(); return HttpClientBuilder.create() .setDefaultCredentialsProvider(provider) .setDefaultRequestConfig(requestConfig) .build();
内容的提问来源于stack exchange,提问作者user3919727
相关产品推荐
相关产品推荐

