美文网首页
Java与HTTPS

Java与HTTPS

作者: songsongJ | 来源:发表于2017-07-03 16:42 被阅读0次

    什么是HTTPS

    严格地讲,HTTPS并不是一个单独的协议,而是对工作在一加密连接(TLS或SSL)上的常规HTTP协议的称呼。

    TLS/SSL

    关于TLS/SSL的介绍网上已经有很多,大家可以参考《SSL/TLS协议运行机制的概述》《图解SSL/TLS协议》中的介绍

    Java与HTTPS

    JDK中对 HTTPS 版本的支持情况

    • JDK 6
      SSL v3
      TLS v1(默认)
      TLS v1.1(JDK6 update 111 及以上)

    • JDK 7
      SSLv3
      TLS v1(默认)
      TLS v1.1
      TLS v1.2

    • JDK 8
      SSL v3
      TLS v1
      TLS v1.1
      TLS v1.2(默认)

    Java在使用HTTPS时遇到的问题

    首先看一个错误:

    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)
    

    背景

    最近在使用的第三方接口升级了TLS协议,只支持TLSv1.2,而我们的机器使用的JDK版本为JDK1.7,默认使用的是TLSv1,所以当服务端只支持TLSv1.2时会报异常

    解决

    解决方案很简单,只需要在启动参数加上-Dhttps.protocols=TLSv1.2即可

    下面我们验证下此解决方案是否有效

    • 使用 HttpURLConnection发送HTTPS请求访问百度(未修改启动参数)
    /**
     * 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抓包可以看到使用的协议为TLSv1(JDK1.7)
    • 修改启动参数(jdk1.7)

    再次请求 可以看到协议变为TLSv1.2

    • 使用JDK1.8我们再看看

    相关文章

      网友评论

          本文标题:Java与HTTPS

          本文链接:https://www.haomeiwen.com/subject/ddiwcxtx.html