【问题标题】:OkHttpClient redirects http URL to Https and gives SSLException with https URLOkHttpClient 将 http URL 重定向到 Https 并给出带有 https URL 的 SSLException
【发布时间】:2021-03-29 06:52:45
【问题描述】:

我遇到异常,响应通过 OkHttpClient 的 https 休息服务调用

我正在使用库 com.squareup.okhttp3:okhttp-ws:3.4.2。

javax.net.ssl.SSLException:无法识别的 SSL 消息,明文连接? 在 sun.security.ssl.InputRecord.handleUnknownRecord(Unknown Source)

        File certFile = resourceLoader.getResource("classpath:" + certKey).getFile();
        try {
            sslContext = SSLContextBuilder.create()
                    .loadKeyMaterial(certFile, certKeyPassword.toCharArray(), certKeyPassword.toCharArray())
                    .loadTrustMaterial(certFile, certKeyPassword.toCharArray()).build();
        SSLSocketFactory sslSocketFactory = sslContext().getSocketFactory();
        RequestBody formBody = new FormBody.Builder()
                    .add("<key>", "<value>")
                    .build();
        OkHttpClient okHttpClient = new OkHttpClient.Builder().socketFactory(sslSocketFactory).build();
        Request request = new Request.Builder()
                    .url(https URL)
                    .post(formBody)
                    .addHeader("Content-Type", "application/json")
                    .build();
        LOG.info("Request passed: "+request);
        response = okHttpClient.newCall(request).execute();

当我使用 http URL 时,它会将 https URL 发送到交互应用程序。 但在日志中,我在执行调用之前打印,它只显示 http URL

我需要让它与 https URL 一起使用。

如果需要任何其他信息,请告诉我。

【问题讨论】:

    标签: java http ssl https okhttp


    【解决方案1】:

    您不小心将 sslSocketFactory 传递给了 socketFactory。

    OkHttpClient okHttpClient = new OkHttpClient.Builder().socketFactory(sslSocketFactory).build();
    

    你想要

    OkHttpClient okHttpClient = new OkHttpClient.Builder().sslSocketFactory(sslSocketFactory, trustManager).build();
    

    您必须使用一个非常旧的 OkHttp 版本,因为这是经过多年专门检查的。

        /**
         * Sets the socket factory used to create connections. OkHttp only uses the parameterless
         * [SocketFactory.createSocket] method to create unconnected sockets. Overriding this method,
         * e. g., allows the socket to be bound to a specific local address.
         *
         * If unset, the [system-wide default][SocketFactory.getDefault] socket factory will be used.
         */
        fun socketFactory(socketFactory: SocketFactory) = apply {
          require(socketFactory !is SSLSocketFactory) { "socketFactory instanceof SSLSocketFactory" }
    
          if (socketFactory != this.socketFactory) {
            this.routeDatabase = null
          }
    
          this.socketFactory = socketFactory
        }
    

    【讨论】:

    • 在更高的环境中,我收到以下异常 java.net.UnknownHostException: : Temporary failure in name resolution
    • 我也添加了 NoopH​​ostNameVerifier,但仍然没有运气。 return new OkHttpClient().newBuilder().sslSocketFactory(sslSocketFactory).hostnameVerifier(NoopHostnameVerifier.INSTANCE).build();
    • 谢谢尤里。使用 sslSocketFactory 方法代替 socketFactory 方法解决了我的问题,如下所示。OkHttpClient okHttpClient = new OkHttpClient().newBuilder().sslSocketFactory(sslSocketFactory).build()
    • 该方法已被弃用,很奇怪您选择了那个方法,它在某些平台上确实失败了。所以你的代码不会是可移植的。
    猜你喜欢
    • 2015-11-02
    • 2020-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-05
    • 2017-04-20
    相关资源
    最近更新 更多