编程语言
首页 > 编程语言> > 允许Java JDK 11 HttpClient的不安全的HTTPS连接

允许Java JDK 11 HttpClient的不安全的HTTPS连接

作者:互联网

有时需要允许不安全的HTTPS连接,例如在一些应该适用于任何网站的网络爬行应用程序中.我使用旧的HttpsURLConnection API使用了one such solution,最近被JDK 11中的new HttpClient API取代了.使用这个新API允许不安全的HTTPS连接(自签名或过期证书)的方法是什么?

UPD:我尝试的代码(在Kotlin中,但直接映射到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):

java.io.IOException: No name matching localhost found

使用IP地址而不是localhost会出现“无主题替代名称存在”异常.

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

解决方法:

使用Java 11,您可以使用HttpClient进行类似的努力as mentioned in the selected answer in the link shared

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

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

-Djdk.internal.httpclient.disableHostnameVerification

可以是set programmatically如下: –

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

标签:java-11,java,java-http-client
来源: https://codeday.me/bug/20191004/1854634.html