Tomcat9升级后调用Trustspot接口SSL握手报close_notify异常如何解决
问题根因
该异常的核心原因是服务器环境的椭圆曲线加密支持异常,导致TLS 1.2握手时ClientHello报文未携带elliptic_curves、ec_point_formats扩展,而目标接口仅支持ECDHE系列的TLS加密套件,服务端识别到缺少必要的EC扩展后找不到可用的加密套件,直接返回close_notify中断握手。
你本地运行正常是因为本地JRE为完整版本,默认启用了EC加密支持;修改-Dhttps.protocols参数无效的原因是旧版Apache HttpComponents的DefaultHttpClient不会读取JVM全局的HTTPS配置,其SSL连接逻辑独立管理。
解决方案
- 检查修复JDK的EC加密支持
- 确认服务器使用的JRE目录下
jre/lib/ext/路径存在sunec.jar文件,该文件是JDK实现椭圆曲线加密的核心扩展包,若缺失从同版本的完整JDK包中拷贝对应文件到该路径即可 - 打开
jre/lib/security/java.security配置文件,检查jdk.tls.disabledAlgorithms配置项,删除其中的EC、ECDHE相关禁用规则,保存后重启服务
- 确认服务器使用的JRE目录下
- 手动指定HttpClient的SSL上下文
不要依赖DefaultHttpClient的默认SSL配置,手动构造支持TLS 1.2和EC算法的SSL上下文注入到客户端,参考代码如下:
若业务有严格的域名校验需求,可将import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.BasicClientConnectionManager; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.ssl.SSLSocketFactory; import javax.net.ssl.SSLContext; import java.security.SecureRandom; // 构造自定义SSL上下文 SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(null, null, new SecureRandom()); // 注册HTTPS协议配置 SSLSocketFactory sslSocketFactory = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("https", 443, sslSocketFactory)); // 构造带自定义配置的HttpClient HttpClient httpClient = new DefaultHttpClient(new BasicClientConnectionManager(schemeRegistry));ALLOW_ALL_HOSTNAME_VERIFIER替换为默认的域名校验逻辑。 - 新增JVM启动参数强制指定EC曲线
若上述操作后仍未生效,在Tomcat启动参数中新增以下配置:-Djdk.tls.namedGroups=secp256r1,secp384r1,secp521r1 -Dhttps.protocols=TLSv1.2
该参数会强制TLS握手时携带指定的椭圆曲线列表,补全缺失的扩展字段。
验证方法
修改完成后,添加JVM启动参数-Djavax.net.debug=ssl:handshake重启服务,再次发起请求查看日志,确认ClientHello报文中已出现elliptic_curves扩展字段和对应的曲线列表,此时握手即可正常完成。
内容的提问来源于stack exchange,提问作者Paul Taylor
相关产品推荐
相关产品推荐

