如何在 Java 中更改客户端 TLS 首选项?

2023-12-23

我正在尝试向 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();
}

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


为了在 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 来信任所有证书(自签名)。 为此,请将以下代码添加到您的类中:

    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()

这是一个完整的类示例:

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) {
                }
            } 
        }; 
}

您可以在调用 HttpRequest 时使用 getHttplClient() 函数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Java 中更改客户端 TLS 首选项? 的相关文章

随机推荐

  • Kendo Grid:当行更改时如何从代码更新数据源

    这是我之前几篇关于更新剑道网格数据源的文章的延续 我想做的最后一件事是当用户转到新行时发生这种情况 感谢 Lars 迄今为止提供的令人印象深刻的帮助 我通过检测行更改 碰巧在指令中执行此操作 并回调网格控制器来执行此操作 在网格控制器中我在
  • WSL2 上的 Ubuntu 18.04:“登录失败:尚未授予用户在此计算机上请求的登录类型。”

    重新启动 Windows 计算机后 我在尝试打开 Ubuntu 18 04 WSL2 实例时收到此错误 Logon failure the user has not been granted the requested logon type
  • MongoDB 投影参数在 findOne() 中不起作用

    我试图在 findOne 上使用投影参数从文档 统计信息 中提取单个字段 但它似乎只是返回整个文档 我在 Node js 中使用版本 mongodb 3 4 1 这是文档结构 id 5e563015fa9a1a0134cac3cb user
  • javascript图形库[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个不错的 JavaScript 图形库 它可以处理以下类型的图形 折线图 直方图 散点图 动态图表 我已经尝试过 Google
  • 防止伪元素自行断行

    我有一个链接样式 可以使用以下命令在链接末尾添加 SVG 箭头 after 问题是 当视口改变大小时 有时只有 SVG 会断线 我怎样才能设置它 以便 SVG 总是用最后一个单词来换行 a tag txtbtn font size 1 12
  • PHP预防xss

    Is htmlentitiesPHP 中防止 XSS 的最佳解决方案 我也想允许简单的标签 比如b i a and img 实现这一点的最佳解决方案是什么 我确实考虑过 bbcode 但发现如果没有正确实现我也会遇到 XSS 问题 我应该怎
  • 当我使用 document.execCommand("copy") 时,javascript 换行符不适用

    您好 我正在使用下面的代码构建一个字符串并复制它 但是在粘贴它时的输出中 换行符不适用 function copyToClipboardShipto var temp
  • 在 Orchard 中创建/编辑后清空内容项

    我正在使用在 Orchard 中创建 n to n 关系的指南 ocs orchardproject net Documentation Creating 1 n and n n relations 并进行一些细微的修改 虽然示例代码运行良
  • 移动语义和原始类型

    示例代码 int main std vector
  • 将文本搜索 where 子句添加到 SPARQL 查询

    我得到了一个我认为是简单的任务 获取现有的 SPARQL 查询并调整 WHERE 子句以将结果限制为特定文本字段包含特定搜索词的实体 但是 我对 SPARQL 语言完全陌生 我尝试过的任何方法都不起作用 看来我需要使用text query
  • spring 环境特定的 log4j 配置

    我正在使用传统方式加载 log4j xml
  • 使用自定义 KMS 密钥访问 AWS 参数存储值

    我正在尝试使用 java 从参数存储中读取 AWS 参数 我已使用自定义加密密钥创建了参数 我在互联网上没有看到使用自定义 KMS 密钥的示例代码 下面是我当前正在运行的代码 这里我们使用默认的 KMS 密钥 AWSSimpleSystem
  • 使用 PHP 仅获取除法的余数

    我正在划分19 5我在哪里用过19 5但我无法得到剩余的only 我如何得到它 谢谢 让 echo 19 5 应返回 4 即 19 5 的余数 3 rem 4 不需要使用下限 因为模运算的结果始终是整数值 如果您在处理浮点值时想要余数 那么
  • iOS - 请求在初次拒绝后启用推送通知

    我想知道在最初拒绝后是否可以从应用程序内强制弹出 XXXXX 想向您发送推送通知 用例如下 用户安装应用程序 获取有关推送通知的警报 并拒绝 因为他们还不知道 信任该应用程序 他们使用该应用程序并主动在应用程序内请求收到警报 当某事发生时
  • 如何去除应用栏上方的阴影?

    我想通过添加使状态栏透明
  • 使用 Eclipse 和 Tomcat 的 JSF 2.0 教程 [已关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 获取一段文本中最后一行的宽度

    是否可以以某种方式测量具有多个中断 回车的段落中最后一行文本的长度 Morbi leo risus porta ac consectetur ac vestibulum at eros Donec id elit non mi porta
  • 如何在 Midnight Commander 中使用 panelize?我想知道,因为这是对选定文件和目录进行递归 chmod 的一种方法

    我知道我可以使用 chmod 和高级 chmod 但他们没有为我提供一种方法递归地更改文件和文件夹的权限 Panelize 似乎能够做到这一点 但是 如果我使用 Ctrl t 选择文件然后选择 panelize 我似乎没有得到任何结果 我不
  • F# 记录与 .net 结构

    f 记录与 net 结构相同吗 我看到人们谈论 f 结构 他们使用这个术语可以与 F 记录互换吗 像FSharp 运行我的算法比 Python 慢 https stackoverflow com questions 5850243 fsha
  • 如何在 Java 中更改客户端 TLS 首选项?

    我正在尝试向 Java 中的端点发出 POST 请求 当我尝试发送请求时 出现以下错误 Caused by javax net ssl SSLHandshakeException The server selected protocol v