【问题标题】:Apache HttpClient - Log version of TLS that's negotiated in a request?Apache HttpClient - 在请求中协商的 TLS 日志版本?
【发布时间】:2018-04-17 14:21:32
【问题描述】:

我有很多使用 Apache 的 HttpClient 的代码,我想记录发出请求时正在协商的 TLS 版本。

这可能吗?

如果可能的话,我更喜欢一种不需要更改请求的构建方式的方法 - 检查响应或查看日志或类似的东西?

根据我的评论,这似乎只有在我们在 VM 级别调试 SSL 或者使用自定义 SSLContext 时才有可能?

【问题讨论】:

    标签: java java-8 apache-httpclient-4.x


    【解决方案1】:

    如果您为org.apache.http.conn.ssl 类别打开调试级别日志记录,HttpClient 将记录有关所使用的 SSL 会话的大量详细信息,包括 TLS/SSL 协议版本。

    [DEBUG] DefaultHttpClientConnectionOperator - Connecting to httpbin.org/54.225.150.40:443
    [DEBUG] SSLConnectionSocketFactory - Connecting socket to httpbin.org/54.225.150.40:443 with timeout 0
    [DEBUG] SSLConnectionSocketFactory - Enabled protocols: [TLSv1, TLSv1.1, TLSv1.2]
    [DEBUG] SSLConnectionSocketFactory - Enabled cipher suites:[TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
    [DEBUG] SSLConnectionSocketFactory - Starting handshake
    [DEBUG] SSLConnectionSocketFactory - Secure session established
    [DEBUG] SSLConnectionSocketFactory -  negotiated protocol: TLSv1.2
    [DEBUG] SSLConnectionSocketFactory -  negotiated cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    [DEBUG] SSLConnectionSocketFactory -  peer principal: CN=httpbin.org
    [DEBUG] SSLConnectionSocketFactory -  peer alternative names: [httpbin.org, www.httpbin.org]
    [DEBUG] SSLConnectionSocketFactory -  issuer principal: CN=Let's Encrypt Authority X3, O=Let's Encrypt, C=US
    [DEBUG] DefaultHttpClientConnectionOperator - Connection established 192.168.43.64:57534<->54.225.150.40:443
    

    【讨论】:

    • org.apache.http.conn.ssl 似乎不存在于 Android 中的 Apache HTTP 客户端中。你能确认一下吗?如果是,是否有其他方法可以获取 SSL 日志?
    【解决方案2】:

    另外,另一种可能性是创建自定义SSLContext 并从打开的会话中获取信息:

        private static String URL = "https://www.google.com";
        private static String TRUST_STORE_FILE = "/Users/xpto/trust.p12";
        private static String TRUST_STORE_PASS = "truststore";
        private static String TRUST_STORE_TYPE = "PKCS12";
        private static String TLS_VERSION = "TLSv1.2";
    
        public static void main(String[] args) throws Exception {
            KeyStore keyStore = KeyStore.getInstance(TRUST_STORE_TYPE);
            keyStore.load(new FileInputStream(TRUST_STORE_FILE), TRUST_STORE_PASS.toCharArray());
    
            SSLContext sslContext = SSLContexts
                    .custom()
                    .loadTrustMaterial(keyStore)
                    .useProtocol(TLS_VERSION)
                    .build();
    
            HttpComponentsClientHttpRequestFactory clientFactory = new HttpComponentsClientHttpRequestFactory(HttpClients
                    .custom()
                    .setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext))
                    .build());
    
            RestTemplate restTemplate = new RestTemplate(clientFactory);
    
            HttpHeaders requestHeaders = new HttpHeaders();
            requestHeaders.setContentType(MediaType.APPLICATION_JSON);
            requestHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
    
            HttpEntity<String> requestEntity = new HttpEntity<String>(requestHeaders);
            print("Requesting: " + URL);
            ResponseEntity<String> response = restTemplate.exchange(URL, HttpMethod.GET, requestEntity, String.class);
            print("Response: " + response.getBody());
    
            printSSLContextInfo(sslContext);
        }
    
        private static void printSSLContextInfo(SSLContext sslContext) throws Exception {
            print("-------------\nPrinting TLS Client Information");
            SSLSessionContext sslSessionContext = sslContext.getClientSessionContext();
            Enumeration<byte[]> sessionIds = sslSessionContext.getIds();
            while (sessionIds.hasMoreElements()) {
                SSLSession sslSession = sslSessionContext.getSession(sessionIds.nextElement());
                print("Client: " + sslSession.getPeerHost() + ":" + sslSession.getPeerPort());
                print("\tProtocol: " + sslSession.getProtocol());
                print("\tSessionID: " + byteArrayToHex(sslSession.getId()));
                print("\tCipherSuite: " + sslSession.getCipherSuite());
                for (X509Certificate certificate : sslSession.getPeerCertificateChain()) {
                    print("\tX509 Certificate: " + certificate.getSubjectDN());
                    print("\t\tIssuer: " + certificate.getIssuerDN().getName());
                    print("\t\tAlgorithm: " + certificate.getSigAlgName());
                    print("\t\tValidity: " + certificate.getNotAfter());
                }
            }
        }
    
        public static String byteArrayToHex(byte[] a) {
            StringBuilder sb = new StringBuilder(a.length * 2);
            for (byte b : a)
                sb.append(String.format("%02x", b));
            return sb.toString();
        }
    
        public static void print(Object msg) {
            System.out.println(msg);
        }
    

    我只是分享这个,因为我面临类似的问题,更多参考请参阅:How to obtain all TLS sessions from SSLContext using IBMJSSE2 default provider?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-13
      • 2023-04-06
      • 2019-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多