Java1.7通过TLSv1.2连接api.twilio.com:8443失败Java1.8正常求助
问题原因
- 代码执行顺序错误,SSL配置逻辑晚于连接建立时机。你在调用
connection.getInputStream()时,HttpsURLConnection已经自动完成了握手连接,后续初始化SSLContext、给connection设置SocketFactory的代码完全没有生效。Java 8默认启用TLS1.2,刚好匹配Twilio接口的加密要求,所以可以正常运行;Java 7默认客户端握手使用TLS1.0,而Twilio服务端早已停止支持TLS1.0/1.1,因此直接握手失败。 - Java 7对TLS1.2的默认支持逻辑和Java 8不同:即便设置了
https.protocols系统属性,部分低版本Oracle JDK 7也不会默认将TLS1.2用于客户端SSL握手,需要显式在SSLContext或者SocketFactory层面指定启用的协议。
Java 1.7环境修复方案
调整代码执行顺序,将所有SSL配置、连接配置都放到getInputStream调用之前即可:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; public class SampleApp { public static void main(String[] args) throws IOException, NoSuchAlgorithmException, KeyManagementException { // 先设置系统属性,再初始化任何连接相关对象 System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2"); // 提前初始化TLS1.2的SSLContext并设置为默认 SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(null, null, null); SSLContext.setDefault(sslContext); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); // 初始化连接并设置SocketFactory URL url = new URL("https://api.twilio.com:8443/"); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setSSLSocketFactory(socketFactory); // 最后发起连接读取数据 InputStream is = connection.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String line = null; while ((line = br.readLine()) != null) { System.out.println(line); } } }
如果调整顺序后仍然报错,请将你使用的Oracle JDK 7升级到7u95及以上版本,更早的JDK 7版本对TLS1.2的客户端支持存在缺陷,部分加密套件未内置,也会导致握手失败。
内容的提问来源于stack exchange,提问作者Happs
相关产品推荐
相关产品推荐

