如何在 JAVA 中加速 tls 协商?

How to accelerate tls negotiation in JAVA?

有一个私人网络服务器(支持 https),我需要经常在上面 read/set 一些信息。我编写了一些 java 代码来自动完成。当我使用 Chrome 访问它时,第一次连接很慢(可能 5 秒),但连续连接很快(大约 1S)。使用我的 java 代码,每次都很慢。我知道问题是在与我的代码的每个连接中都执行了完整的 TLS 握手。我的问题是,Chrome 做了什么才能让它更快,我如何在我的代码中模拟它?以下是我的部分代码:

    class MyTrust implements X509TrustManager{
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
        public X509Certificate[] getAcceptedIssuers() {return null; }   
    }

在另一个 class 中建立了连接:

    URLConnection conn = (HttpsURLConnection) url.openConnection();
    SSLContext sc = SSLContext.getInstance("TLS");
    sc.init(null, new TrustManager[] { new MyTrust() }, new java.security.SecureRandom());
    ((HttpsURLConnection) conn).setSSLSocketFactory(sc.getSocketFactory());

我正在阅读 Java Secure Socket Extension (JSSE) Reference Guide,但发现它很难理解。是 SessinID 还是 Principal 有效?谁能给我一些提示?

您的 java 代码每次都会建立连接,因此每次都会执行 TLS 握手。

但是浏览器(例如Chrome)会尝试保持连接(通过在请求中添加Connection:Keep-Alive header),如果服务器接受keep-alive连接(通过在响应中返回 Connection:Keep-Alive header),大多数服务器都会这样做,浏览器将尝试对正在进行的请求使用相同的连接,因此不需要每次都执行 TLS 握手。

对于您的 java 代码,您可以将连接存储在池中,并重新使用它。你可以勾选Apache HttpComponents,它支持http连接池

根据评论编辑:

因为真正的问题是 SSL/TLS session 重用不起作用。我怀疑这是由于滥用 JSSE 造成的。您必须在每个连接上使用相同的 SSLContext 才能启用 session 重用。此外,session 可能会由于连接上的某些错误操作而被丢弃(例如读取流的末尾)。这里列出了一些详细信息:How to enable client TLS session reuse in Java