Tomcat调用Google reCAPTCHA遇SNI错误,独立运行正常求解决
Tomcat环境下调用Google reCAPTCHA出现"No SNI provided, please fix client"错误的解决方法
问题描述
Ubuntu系统上运行的Tomcat应用,向https://www.google.com/recaptcha/api/siteverify发起HTTPS请求时,触发"No SNI provided, please fix client"错误。但使用相同Java环境运行独立Java应用时,相同代码可正常执行。
环境信息
Java version : openjdk version "1.8.0_352" Tomcat Details : Server version: Apache Tomcat/8.5.57 Server built: Jul 16 2020 22:38:29 UTC Server number: 8.5.57.0 OS Name: Linux OS Version: 5.15.0-1028-aws Architecture: amd64 JVM Version: 1.8.0_352-8u352-ga-1~20.04-b08 JVM Vendor: Private Build
涉事代码
public String webRequest(String url) { try { InputStream res = new URL(url).openStream(); BufferedReader rd = new BufferedReader(new InputStreamReader(res, Charset.forName("UTF-8"))); StringBuilder sb = new StringBuilder(); int cp; while ((cp = rd.read()) != -1) { sb.append((char) cp); } res.close(); return sb.toString(); }catch (Exception e) { return ""; } }
错误日志片段
javax.net.ssl|FINE|19|http-nio-8080-exec-8|2023-01-24 23:19:20.155 UTC|CertificateMessage.java:366|Consuming server Certificate handshake message ( "Certificates": [ "certificate" : { "version" : "v3", "serial number" : "00 90 76 89 18 E9 33 93 A0", "signature algorithm": "SHA256withRSA", "issuer" : "CN=invalid2.invalid, OU="No SNI provided; please fix your client."", "not before" : "2015-01-01 24:00:00.000 UTC", "not after" : "2030-01-01 24:00:00.000 UTC", "subject" : "CN=invalid2.invalid, OU="No SNI provided; please fix your client."", "subject public key" : "RSA", "extensions" : [
解决方案
原因
SNI(服务器名称指示)是HTTPS握手时客户端告知服务器目标域名的扩展字段,Google服务器要求必须提供该字段才能返回有效证书。Tomcat环境下默认的URLConnection可能未启用SNI,而独立Java应用的默认配置已开启,或Tomcat的SSL配置干扰了全局HTTPS客户端行为。
修复方式
方式1:修改代码显式启用SNI
调整请求代码,手动配置HttpsURLConnection启用SNI:
public String webRequest(String url) { try { URL targetUrl = new URL(url); HttpsURLConnection conn = (HttpsURLConnection) targetUrl.openConnection(); // 显式设置Host头,确保SNI被传递 conn.setRequestProperty("Host", targetUrl.getHost()); // 确保SSL上下文使用默认配置,支持SNI SSLContext sslContext = SSLContext.getDefault(); conn.setSSLSocketFactory(sslContext.getSocketFactory()); InputStream res = conn.getInputStream(); BufferedReader rd = new BufferedReader(new InputStreamReader(res, Charset.forName("UTF-8"))); StringBuilder sb = new StringBuilder(); int cp; while ((cp = rd.read()) != -1) { sb.append((char) cp); } res.close(); conn.disconnect(); return sb.toString(); } catch (Exception e) { e.printStackTrace(); // 建议保留异常日志便于排查问题 return ""; } }
方式2:添加Tomcat全局JVM参数
在Tomcat启动脚本(如catalina.sh)中添加以下参数,强制启用SNI:
JAVA_OPTS="$JAVA_OPTS -Djsse.enableSNIExtension=true"
注:Java 8u141及以后版本默认启用SNI,但部分Tomcat环境可能被配置禁用,添加此参数可确保功能生效。
方式3:检查Tomcat SSL连接器配置
查看server.xml中的SSL连接器配置,确保SSLEnabled设置为true,且未添加禁用SNI的特殊参数,避免全局JSSE配置被覆盖。
验证
修改完成后重启Tomcat,重新发起请求,确认错误消失,可正常获取Google reCAPTCHA的验证响应。
内容的提问来源于stack exchange,提问作者Martin Joseph
相关产品推荐
相关产品推荐

