如何在Java中改变客户端的TLS偏好?

问题描述 投票:5回答:1

我试图在Java中向一个端点发出POST请求,当我试图发送请求时,我得到以下错误。

Caused by: javax.net.ssl.SSLHandshakeException: The server selected protocol version TLS10 is not accepted by client preferences [TLS13, TLS12]

这是我目前所掌握的情况

Map<Object, Object> data = new HashMap<>();
data.put("username","foo");
data.put("password","bar");

String url = "https://google.com";

HttpRequest request = HttpRequest.newBuilder()
     .POST(buildFormDataFromMap(data))
     .uri(URI.create(url))
     .build();

try{
     HttpResponse<String> response =  httpClient.send(request, 
          HttpResponse.BodyHandlers.ofString());
     System.out.println(response.statusCode());
     System.out.println(response.body());
} catch (Exception e){
     e.printStackTrace();
}

然后当我运行这段代码时,在发送requestmaking响应对象时,就会抛出错误。我的问题是,如果服务器的TLS首选项与客户端不同,我如何在Java中改变首选项,使它仍然可以发出请求?

tls1.2 sslhandshakeexception tls1.0
1个回答
1
投票

为了在jdk 11中解决这个问题,我不得不创建一个javax.net.ssl.SSLParameters对象来启用 "TLSv1 "等。

SSLParameters sslParameters = new SSLParameters();
        sslParameters.setProtocols(new String[]{"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"});

然后创建HttpClient并添加sslParamters对象。

HttpClient httpClient = HttpClient.newBuilder()
            .sslParameters(sslParameters)
            .build();

如果你也想禁用主机名验证,在HttpClient初始化前添加以下代码。

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

你也可以添加一个新的TrustManager来信任所有的证书(自签名).为了做到这一点,在你的Class中添加以下代码。

    TrustManager[] trustAllCerts = new TrustManager[] { 
        new X509TrustManager() {     
            public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
                return new X509Certificate[0];
            } 
            public void checkClientTrusted( 
                java.security.cert.X509Certificate[] certs, String authType) {
                } 
            public void checkServerTrusted( 
                java.security.cert.X509Certificate[] certs, String authType) {
            }
        } 
    }; 

在这之后,你必须创建一个SSLContext对象并添加TrustManger对象。

SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

最后像这样修改HttpClient的初始化。

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

这是一个完整的Class例子

import java.net.http.HttpClient;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.Properties;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class HttpSSLClient {

    private SSLContext sslContext;
    private SSLParameters sslParameters;
    private HttpClient httpClient;

    public HttpSSLClient() throws KeyManagementException, NoSuchAlgorithmException {

        sslParameters = new SSLParameters();
        sslParameters.setProtocols(new String[]{"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"});

        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

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

        httpClient = HttpClient.newBuilder()
                .sslContext(sslContext)
                .sslParameters(sslParameters)
                .build();
    }

    public HttpClient getHttplClient() {
        return httpClient;
    }

    TrustManager[] trustAllCerts = new TrustManager[] { 
            new X509TrustManager() {     
                public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
                    return new X509Certificate[0];
                } 
                public void checkClientTrusted( 
                    java.security.cert.X509Certificate[] certs, String authType) {
                    } 
                public void checkServerTrusted( 
                    java.security.cert.X509Certificate[] certs, String authType) {
                }
            } 
        }; 
}

你可以使用getHttplClient()函数来调用你的HttpRequest.

© www.soinside.com 2019 - 2024. All rights reserved.