javax.net.ssl.SSLException:从 Apache Tomcat 9.0.54 发送请求时在握手错误期间收到 close_notify
javax.net.ssl.SSLException: Received close_notify during handshake error when sending request from Apache Tomcat 9.0.54
我已将我的网站从一台非常旧的服务器移至一台支持 SSL 的新服务器,并从 Apache Tomcat 6 升级到 Apache Tomcat 9.0.54。现在,当我服务器上的代码 运行ning 尝试使用此代码
向 trustspot 服务器(受信任的评论站点)发送请求时
try
{
HttpClient httpclient = new DefaultHttpClient();
this.order=order;
String dataForHmac = MERCHANT_ID + order.getOrderId() + order.getCustomerEmail();
String calculatedHmac = base64sha256(dataForHmac, SECRET_KEY);
order.setHmac(calculatedHmac);
order.setKey(API_KEY);
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).setPrettyPrinting().create();
System.out.println(gson.toJson(order));
String jsonData = gson.toJson(order);
url = new URL("https://trustspot.io/api/pub/new_order_product");
httpMethod = new HttpPost(url.toExternalForm());
httpMethod.addHeader("Content-Type", "application/json");
StringEntity se = new StringEntity(jsonData);
httpMethod.setEntity(se);
HttpResponse httpResponse = httpclient.execute(httpMethod);
InputStreamReader is = new InputStreamReader(httpResponse.getEntity().getContent());
BufferedReader rd;
rd = new BufferedReader(is);
String line = "";
while ((line = rd.readLine()) != null)
{
System.out.println(line);
}
}
catch(Exception ex)
{
StringWriter messageBody = new StringWriter();
PrintWriter pw = new PrintWriter(messageBody);
ex.printStackTrace(pw);
Email.sendAlert("Unable to send trustpot review request:"+ order.getCustomerEmail(), messageBody.toString());
}
我明白了
javax.net.ssl.SSLException: Received close_notify during handshake
我该如何解决这个问题?
javax.net.ssl.SSLException: Received close_notify during handshake
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1959)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1911)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2012)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1135)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:553)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:412)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:179)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:328)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:612)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:447)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:884)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
at com.jthink.store.trustspot.TrustSpotProductRequest.sendRequest(TrustSpotProductRequest.java:68)
at com.jthink.store.googleprocess.AbstractCreateAndSendLicense.requestReview(AbstractCreateAndSendLicense.java:306)
at com.jthink.store.googleprocess.CreateAndSendSongKongLicense.createAndSendLicense(CreateAndSendSongKongLicense.java:120)
at com.jthink.store.action.VerifyPaymentEJunkie.processEachItem(VerifyPaymentEJunkie.java:169)
at com.jthink.store.action.VerifyPaymentEJunkie.handleRequest(VerifyPaymentEJunkie.java:82)
at com.jthink.store.JThinkStoreServlet.doGet(JThinkStoreServlet.java:45)
at com.jthink.store.JThinkStoreServlet.doPost(JThinkStoreServlet.java:32)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
我正在使用 Java 1.8.0_161-b12
尝试在设置 -Dhttps.protocols=TLSv1
和 -Dhttps.protocols=TLSv1.1, TLSv1.2
后重新启动 Tomcat 但没有任何区别
更新
添加了一个 main() 到 class 所以现在我可以 运行 在 tomcat 之外的机器上测试并且它以完全相同的方式失败
java -classpath classes:lib/* com.jthink.store.trustspot.TrustSpotProductRequest -Dhttps.protocols=TLSv1
给出相同的异常
javax.net.ssl.SSLException: Received close_notify during handshake
运行在我的电脑上使用完全相同的代码工作正常。
更新 2
随着-Djavax.net.debug=ssl:handshake
trigger seeding of SecureRandom
done seeding SecureRandom
main, setSoTimeout(0) called
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1.1
%% No cached client session
*** ClientHello, TLSv1.2
RandomCookie: GMT: 1621095199 bytes = { 214, 189, 173, 184, 228, 255, 156, 82, 153, 122, 143, 245, 185, 144, 166, 172, 32, 10, 144, 123, 158, 248, 38, 4, 84, 67, 13, 79 }
Session ID: {}
Cipher Suites: [TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods: { 0 }
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Extension extended_master_secret
Extension server_name, server_name: [type=host_name (0), value=trustspot.io]
***
main, WRITE: TLSv1.2 Handshake, length = 146
main, READ: TLSv1.2 Alert, length = 2
main, RECV TLSv1.2 ALERT: warning, close_notify
main, SEND TLSv1.2 ALERT: fatal, description = unexpected_message
main, WRITE: TLSv1.2 Alert, length = 2
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLException: Received close_notify during handshake
main, called close()
main, called closeInternal(true)
在我的电脑上,我能看到的区别是它也有扩展名 elliptic_curves 和扩展名 ec_point_formats, 我需要它们吗?
握手的长度也不同。
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, secp384r1, secp521r1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Extension extended_master_secret
Extension server_name, server_name: [type=host_name (0), value=trustspot.io]
***
main, WRITE: TLSv1.2 Handshake, length = 214
main, READ: TLSv1.2 Handshake, length = 91
通常 SSL 问题与证书问题有关,您确定您的旧证书仍然有效且配置正确,如果不是,我建议先将其添加到服务器中
问题是我的 Java 版本,(答案来自@dave_thompson_085 评论,我不完全理解细节,如果解释不完全正确,请原谅我)
我在 linux centos 机器上使用 Java 1.8.0_161-b12,结果发现这个版本不支持 TLS 1.2 的椭圆曲线套件,但我连接的服务器仅支持 ECHDE,这需要使用椭圆曲线算法,因此无法正常工作。
已更新到 jdk1.8.0_202 并且现在可以使用
我已将我的网站从一台非常旧的服务器移至一台支持 SSL 的新服务器,并从 Apache Tomcat 6 升级到 Apache Tomcat 9.0.54。现在,当我服务器上的代码 运行ning 尝试使用此代码
向 trustspot 服务器(受信任的评论站点)发送请求时 try
{
HttpClient httpclient = new DefaultHttpClient();
this.order=order;
String dataForHmac = MERCHANT_ID + order.getOrderId() + order.getCustomerEmail();
String calculatedHmac = base64sha256(dataForHmac, SECRET_KEY);
order.setHmac(calculatedHmac);
order.setKey(API_KEY);
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).setPrettyPrinting().create();
System.out.println(gson.toJson(order));
String jsonData = gson.toJson(order);
url = new URL("https://trustspot.io/api/pub/new_order_product");
httpMethod = new HttpPost(url.toExternalForm());
httpMethod.addHeader("Content-Type", "application/json");
StringEntity se = new StringEntity(jsonData);
httpMethod.setEntity(se);
HttpResponse httpResponse = httpclient.execute(httpMethod);
InputStreamReader is = new InputStreamReader(httpResponse.getEntity().getContent());
BufferedReader rd;
rd = new BufferedReader(is);
String line = "";
while ((line = rd.readLine()) != null)
{
System.out.println(line);
}
}
catch(Exception ex)
{
StringWriter messageBody = new StringWriter();
PrintWriter pw = new PrintWriter(messageBody);
ex.printStackTrace(pw);
Email.sendAlert("Unable to send trustpot review request:"+ order.getCustomerEmail(), messageBody.toString());
}
我明白了
javax.net.ssl.SSLException: Received close_notify during handshake
我该如何解决这个问题?
javax.net.ssl.SSLException: Received close_notify during handshake
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1959)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1911)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2012)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1135)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:553)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:412)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:179)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:328)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:612)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:447)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:884)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
at com.jthink.store.trustspot.TrustSpotProductRequest.sendRequest(TrustSpotProductRequest.java:68)
at com.jthink.store.googleprocess.AbstractCreateAndSendLicense.requestReview(AbstractCreateAndSendLicense.java:306)
at com.jthink.store.googleprocess.CreateAndSendSongKongLicense.createAndSendLicense(CreateAndSendSongKongLicense.java:120)
at com.jthink.store.action.VerifyPaymentEJunkie.processEachItem(VerifyPaymentEJunkie.java:169)
at com.jthink.store.action.VerifyPaymentEJunkie.handleRequest(VerifyPaymentEJunkie.java:82)
at com.jthink.store.JThinkStoreServlet.doGet(JThinkStoreServlet.java:45)
at com.jthink.store.JThinkStoreServlet.doPost(JThinkStoreServlet.java:32)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
我正在使用 Java 1.8.0_161-b12
尝试在设置 -Dhttps.protocols=TLSv1
和 -Dhttps.protocols=TLSv1.1, TLSv1.2
后重新启动 Tomcat 但没有任何区别
更新 添加了一个 main() 到 class 所以现在我可以 运行 在 tomcat 之外的机器上测试并且它以完全相同的方式失败
java -classpath classes:lib/* com.jthink.store.trustspot.TrustSpotProductRequest -Dhttps.protocols=TLSv1
给出相同的异常
javax.net.ssl.SSLException: Received close_notify during handshake
运行在我的电脑上使用完全相同的代码工作正常。
更新 2
随着-Djavax.net.debug=ssl:handshake
trigger seeding of SecureRandom
done seeding SecureRandom
main, setSoTimeout(0) called
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1.1
%% No cached client session
*** ClientHello, TLSv1.2
RandomCookie: GMT: 1621095199 bytes = { 214, 189, 173, 184, 228, 255, 156, 82, 153, 122, 143, 245, 185, 144, 166, 172, 32, 10, 144, 123, 158, 248, 38, 4, 84, 67, 13, 79 }
Session ID: {}
Cipher Suites: [TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods: { 0 }
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Extension extended_master_secret
Extension server_name, server_name: [type=host_name (0), value=trustspot.io]
***
main, WRITE: TLSv1.2 Handshake, length = 146
main, READ: TLSv1.2 Alert, length = 2
main, RECV TLSv1.2 ALERT: warning, close_notify
main, SEND TLSv1.2 ALERT: fatal, description = unexpected_message
main, WRITE: TLSv1.2 Alert, length = 2
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLException: Received close_notify during handshake
main, called close()
main, called closeInternal(true)
在我的电脑上,我能看到的区别是它也有扩展名 elliptic_curves 和扩展名 ec_point_formats, 我需要它们吗?
握手的长度也不同。
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, secp384r1, secp521r1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Extension extended_master_secret
Extension server_name, server_name: [type=host_name (0), value=trustspot.io]
***
main, WRITE: TLSv1.2 Handshake, length = 214
main, READ: TLSv1.2 Handshake, length = 91
通常 SSL 问题与证书问题有关,您确定您的旧证书仍然有效且配置正确,如果不是,我建议先将其添加到服务器中
问题是我的 Java 版本,(答案来自@dave_thompson_085 评论,我不完全理解细节,如果解释不完全正确,请原谅我)
我在 linux centos 机器上使用 Java 1.8.0_161-b12,结果发现这个版本不支持 TLS 1.2 的椭圆曲线套件,但我连接的服务器仅支持 ECHDE,这需要使用椭圆曲线算法,因此无法正常工作。
已更新到 jdk1.8.0_202 并且现在可以使用