允许Java JDK 11 HttpClient的不安全的HTTPS连接 [英] Allow insecure HTTPS connection for Java JDK 11 HttpClient

查看:990
本文介绍了允许Java JDK 11 HttpClient的不安全的HTTPS连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时需要允许不安全的HTTPS连接,例如在一些应该与任何站点一起使用的Web爬行应用程序中。我使用一个这样的解决方案旧的HttpsURLConnection API最近被JDK中的新的HttpClient API 取代11.使用这个新API允许不安全的HTTPS连接(自签名或过期证书)的方法是什么?

Sometimes it is needed to allow insecure HTTPS connections, e.g. in some web-crawling applications which should work with any site. I used one such solution with old HttpsURLConnection API which was recently superseded by the new HttpClient API in JDK 11. What is the way to allow insecure HTTPS connections (self-signed or expired certificate) with this new API?

UPD:我尝试的代码(在Kotlin但是地图直接到Java):

UPD: The code I tried (in Kotlin but maps directly to Java):

    val trustAllCerts = arrayOf<TrustManager>(object: X509TrustManager {
        override fun getAcceptedIssuers(): Array<X509Certificate>? = null
        override fun checkClientTrusted(certs: Array<X509Certificate>, authType: String) {}
        override fun checkServerTrusted(certs: Array<X509Certificate>, authType: String) {}
    })

    val sslContext = SSLContext.getInstance("SSL")
    sslContext.init(null, trustAllCerts, SecureRandom())

    val sslParams = SSLParameters()
    // This should prevent host validation
    sslParams.endpointIdentificationAlgorithm = ""

    httpClient = HttpClient.newBuilder()
        .sslContext(sslContext)
        .sslParameters(sslParams)
        .build()

但在发送时我有异常(尝试使用自签名证书的localhost):

But on sending I have exception (trying on localhost with self-signed certificate):

java.io.IOException: No name matching localhost found

使用IP地址而不是localhost给出没有主题替代名称存在异常。

Using IP address instead of localhost gives "No subject alternative names present" exception.

经过一些JDK调试后我发现 sslParams 在抛出异常的地方被忽略,并且使用了一些本地创建的实例。进一步调试显示,影响主机名验证算法的唯一方法是将 jdk.internal.httpclient.disableHostnameVerification 系统属性设置为true。这似乎是一个解决方案。上面代码中的 SSLParameters 无效,因此可以丢弃此部分。使其仅在全局配置看起来像是新的HttpClient API中的严重设计缺陷。

After some debugging of JDK I found that sslParams are really ignored in the place the exception is thrown and some locally created instance is used. Further debugging revealed that the only way to affect the hostname verification algorithm is setting jdk.internal.httpclient.disableHostnameVerification system property to true. And that's seems to be a solution. SSLParameters in the code above have no effect so this part can be discarded. Making it configurable only globally looks like serious design flaw in new HttpClient API.

推荐答案

使用Java 11,你也可以做一个类似的工作在共享的链接中选定的答案中提到 HttpClient 内置为:

With Java 11, as well you can do a similar effort as mentioned in the selected answer in the link shared with the HttpClient built as:

HttpClient httpClient = HttpClient.newBuilder()
        .connectTimeout(Duration.ofMillis(<timeoutInSeconds> * 1000))
        .sslContext(sc) // SSL context 'sc' initialised as earlier
        .sslParameters(parameters) // ssl parameters if overriden
        .build();

带样品请求

HttpRequest requestBuilder = HttpRequest.newBuilder()
            .uri(URI.create("https://www.example.com/getSomething"))
            .GET()
            .build();

可以执行:

httpClient.send(requestBuilder, HttpResponse.BodyHandlers.ofString()); // sends the request






从评论更新到禁用主机名验证,目前可以使用系统属性:


Update from comments, to disable the hostname verification, currently one can use the system property:

-Djdk.internal.httpclient.disableHostnameVerification

可以以编程方式设置如下: -

final Properties props = System.getProperties(); 
props.setProperty("jdk.internal.httpclient.disableHostnameVerification", Boolean.TRUE.toString());

这篇关于允许Java JDK 11 HttpClient的不安全的HTTPS连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆