什么是HTTPS
嚴(yán)格地講变姨,HTTPS并不是一個(gè)單獨(dú)的協(xié)議,而是對(duì)工作在一加密連接(TLS或SSL)上的常規(guī)HTTP協(xié)議的稱呼熬北。
TLS/SSL
關(guān)于TLS/SSL的介紹網(wǎng)上已經(jīng)有很多,大家可以參考《SSL/TLS協(xié)議運(yùn)行機(jī)制的概述》和 《圖解SSL/TLS協(xié)議》中的介紹
Java與HTTPS
JDK中對(duì) HTTPS 版本的支持情況
JDK 6
SSL v3
TLS v1(默認(rèn))
TLS v1.1(JDK6 update 111 及以上)JDK 7
SSLv3
TLS v1(默認(rèn))
TLS v1.1
TLS v1.2JDK 8
SSL v3
TLS v1
TLS v1.1
TLS v1.2(默認(rèn))
Java在使用HTTPS時(shí)遇到的問題
首先看一個(gè)錯(cuò)誤:
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:196)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
at sun.security.ssl.InputRecord.read(InputRecord.java:480)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:934)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1301)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at httpsTest.HttpsSendTest.basicHttpsGet(HttpsSendTest.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
背景
最近在使用的第三方接口升級(jí)了TLS協(xié)議,只支持TLSv1.2啃擦,而我們的機(jī)器使用的JDK版本為JDK1.7,默認(rèn)使用的是TLSv1饿悬,所以當(dāng)服務(wù)端只支持TLSv1.2時(shí)會(huì)報(bào)異常
解決
解決方案很簡(jiǎn)單令蛉,只需要在啟動(dòng)參數(shù)加上-Dhttps.protocols=TLSv1.2即可
下面我們驗(yàn)證下此解決方案是否有效
- 使用 HttpURLConnection發(fā)送HTTPS請(qǐng)求訪問百度(未修改啟動(dòng)參數(shù))
/**
* Created by wujiang on 2017/6/30.
*/
public class HttpsSendTest {
@Test
public void basicHttpsGet() throws Exception {
String url = "https://www.baidu.com";
URL obj = new URL(url);
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) ...");
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
con.setRequestMethod("GET");
InputStream inputStream = con.getInputStream();
Scanner scanner = new Scanner(inputStream, "UTF-8");
String text = scanner.useDelimiter("\\A").next();
System.out.println(text);
scanner.close();
}
}
- 通過wireShark抓包可以看到使用的協(xié)議為TLSv1(JDK1.7)
- 修改啟動(dòng)參數(shù)(jdk1.7)
再次請(qǐng)求 可以看到協(xié)議變?yōu)門LSv1.2
- 使用JDK1.8我們?cè)倏纯?/li>