当前位置: 首页 > 面试题库 >

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

太叔富
2023-03-14
问题内容

有时需要允许不安全的HTTPS连接,例如在某些可与任何站点一起使用的网络爬网应用程序中。我将这样的解决方案与旧的HttpsURLConnection
API一起使用,该解决方案最近已由JDK 11中的新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中的严重设计缺陷。


问题答案:

同样,对于Java11,您也可以按照与HttpClient构建者共享的链接中的选定答案中所述进行类似的工作:

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

可以通过程序设置如下:

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


 类似资料:
  • 在通过HTTPS访问REST api时,我希望使用Spring RestTemplate使用持久http连接。我不能使它工作;为每个请求创建一个新的连接,并且每次都进行SSL握手。有没有可能通过https使用RestTemplate进行可重用连接,如果有的话,如何配置它? 我设置了一个RestTemplate来通过HTTPS发出请求。那是正确的。然而,我在日志中注意到,每个请求都会发生一次新的SS

  • 问题内容: 我一直在研究从动态Web应用程序中提取信息的程序,该程序运行良好,直到我将tomcat服务器设置为使用具有自签名(因此,不受信任)证书的SSL。错误的堆栈跟踪为: 在Web浏览器中,当用户使用不受信任的证书访问HTTPS站点时,系统会提示用户警告,并要求他设置是否愿意继续进行操作;我想为我的命令行应用程序实现类似的功能…我承认我是套接字编程和网络领域的新手。解决这个问题的任何建议都会很

  • 在过去的几天里,我一直在和Spring保安公司战斗,所以我希望有人能在这里帮助我。 我正在使用Spring Boot 1.2.5 我使用的是Spring Actuator和Spring Remote Shell,它们已经从类路径中删除,认为它们可能会引起问题 我排除了SecurityAutoConfigsion,因为它可能会导致我的问题 这是我的主要课程 这是我的安全配置 我的问题/问题是 > C

  • 首先,我尝试在docker映像上托管一个。这是CURL输出,对我来说没有意义。 尝试:1 TCP_节点延迟设置 连接到本地主机(::1)端口13443(#0) ALPN,提供h2 ALPN,提供http/1.1 密码选择:全部:!出口:!出口40:!出口56:!阿努尔:!低:!RC4:@STRENGTH 已成功设置证书验证位置: CAfile:cfm。wdf。液公司总部:无。0(输出),TLS握手

  • 问题内容: 无论如何,是否需要为使用docker-machine创建的docker守护进程配置 --allow-insecure-ssl 。 命令: 输出: 问题答案: 如果您正在运行稳定的docker-machine v0.2版本,则无法以简便的方式设置docker选项。但是在下一版本v0.3中,使用创建参数解决了该问题。 目前,此功能位于RC1上,然后您可以使用v0.3.0-RC-1版本或等待

  • 我是AWS的新手,并启动了我的第一个EC2实例(AmazonLinux),并为其获得了一个公共IPv4地址。 SSH端口已关闭,实例不响应ping。看起来好像它与互联网完全断开了连接。 我在网上找到的所有帮助都与安全组和打开适当的端口(或ICMP)有关,但我已经这样做了,事实上我甚至设置了相应的安全组以允许所有入站流量。 实例显示Online,可达性检查显示ok。子网的路由表将0.0.0.0/0定