Tomcat9搭配Temurin JDK11连接SendGrid时出现SSLHandshakeException问题
解决Tomcat9使用Java11运行Grails2应用时SendGrid SSL握手失败问题
问题背景
同一测试服务器的Tomcat9部署了两个应用:基于Oracle JDK1.8.0.221构建的Grails2旧应用,以及基于Temurin JDK11.0.13构建的Grails5新应用。为适配Grails5,通过tomcat/bin/setenv.sh将Tomcat的JAVA_HOME设为Java11后,Grails2应用通过SendGrid发送邮件时抛出错误:
SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suite is inappropriate)
尝试调整应用内的TLS版本与密码套件系统属性(如https.protocols、jdk.tls.client.protocols)均无效,需在同一Tomcat实例中同时兼容两个应用,避免运行多版本Java的Tomcat。
核心原因分析
- Java版本安全配置差异:Java11的默认安全策略比Oracle Java8更严格,
jdk.tls.disabledAlgorithms默认禁用了部分旧密码套件(如部分DHE系列套件),而Grails2应用依赖的套件可能在Java11中已被禁用。 - 系统属性生效逻辑变化:Java11中
jdk.tls.client.protocols的优先级与生效方式和Java8不同,应用内直接设置的系统属性可能被全局安全配置覆盖。 - Oracle JDK与OpenJDK差异:Oracle JDK8默认包含部分商业加密套件,而Temurin Java11默认未启用这些套件,导致握手时无合适套件匹配。
可行解决方案
方案1:调整Java11的全局安全配置
修改Java11安装目录下的conf/security/java.security文件:
- 找到
jdk.tls.disabledAlgorithms配置项,移除其中影响TLSv1.2的条目,确保TLSv1.2未被禁用,同时删除对DHE_RSA相关套件的禁用规则(测试环境验证后再考虑生产环境的安全风险)。 - 添加或修改
jdk.tls.client.cipherSuites配置,包含SendGrid支持的TLSv1.2兼容套件,示例:jdk.tls.client.cipherSuites=TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
方案2:在Grails2应用内直接配置SSLContext
替换原有的系统属性设置代码,通过代码显式初始化TLSv1.2的SSLContext,绕过全局配置限制:
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.security.cert.X509Certificate; // 初始化TLSv1.2 SSLContext SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(null, new TrustManager[]{new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) {} @Override public void checkServerTrusted(X509Certificate[] chain, String authType) {} @Override public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];} }}, null); // 设置默认SSL套接字工厂 HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); // 设置主机名验证(适配SendGrid域名) HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> hostname.endsWith("sendgrid.net"));
该方式直接控制SSL握手的协议与验证逻辑,不受全局系统属性影响。
方案3:升级Grails2应用的邮件依赖
检查Grails2应用使用的邮件发送库(如JavaMail)版本,升级至兼容Java11的版本(如JavaMail 1.6.2及以上)。旧版本JavaMail在Java11环境中可能存在SSL握手的兼容性问题,升级后可自动适配新的安全规则。
验证步骤
- 应用修改或配置调整完成后,重启Tomcat9。
- 触发Grails2应用的邮件发送流程,验证是否仍抛出SSL握手异常。
- 可通过
openssl s_client -connect smtp.sendgrid.net:465 -tls1_2命令查看SendGrid支持的密码套件,确保Java11配置中包含对应套件。
内容的提问来源于stack exchange,提问作者ionised
相关产品推荐
相关产品推荐

