java程序跳过https证书验证方式

 更新时间:2026年06月13日 09:07:15   作者:明有所思  
本文详细解析了Java HTTPS接口调用时遇到的SSLHandshakeException问题,并提供了多种解决方案,包括自定义信任管理器和使用Hutool工具等旨在帮助企业解决跨系统接口对接中的的证书验证问题

问题描述

在企业应用开发场景中,跨系统接口对接是常见需求。现代企业往往部署多个异构系统,这些系统由不同供应商开发,采用不同的技术架构实现。系统间需要通过HTTP/HTTPS协议进行功能调用和数据交互。

HTTPS协议的安全机制可能带来开发挑战。当对接方的HTTPS证书存在配置问题时,标准的Java HTTP客户端会因证书验证失败而拒绝连接。

Java安全体系对HTTPS连接有严格的证书验证机制。客户端会检查服务器证书的颁发机构、有效期、域名匹配等信息。任何一项验证失败都会导致SSLHandshakeException异常。当对接方使用自签名证书或证书链不完整时,这种严格验证机制反而会成为系统集成的障碍。

这种情况通常需要特殊处理,暂时绕过证书验证环节,以保障系统间的正常通信。

问题复现

未跳过验证的代码

public static String request(String requestUrl,
                                                  String requestMethod, String body, String contentType, Map<String, String> heads)  throws Exception{
        HttpsURLConnection connection;
        StringBuilder buffer = new StringBuilder();
        try {


            URL url = new URL(requestUrl);
            connection = (HttpsURLConnection) url.openConnection();
            // 创建不验证主机名的 HostnameVerifier
            connection.setHostnameVerifier((hostname, session) -> true);

            // 设置请求头属性
            if(heads != null){
                for (Map.Entry<String, String> map : heads.entrySet()) {
                    String key = map.getKey();
                    String value = map.getValue();
                    connection.setRequestProperty(key, value);
                }
            }

            // 设置请求方式
            connection.setRequestMethod(requestMethod);

            if (StrUtil.isNotEmpty(contentType)){
                connection.setRequestProperty("content-type", contentType);
            }
            // 当有数据需要提交时
            if (null != body) {
                OutputStream outputStream = connection.getOutputStream();
                // 设置编码格式,防止中文乱码
                outputStream.write(body.getBytes("UTF-8"));
                outputStream.close();
            }

            // 将返回的输入流转换成字符串
            InputStream inputStream = connection.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(
                    inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(
                    inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            connection.disconnect();
            return buffer.toString();
        } catch (Exception e) {
            throw new Exception(e);
        }
    }

运行结果

调用上述方法后,运行出现了" javax.net.ssl.SSLHandshakeException"的错误,看这句错误 提示信息:

Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target。

这条错误提示信息意味着Java无法找到一条有效的证书链来验证请求的目标(通常是服务器)的证书。

这通常是因为服务器的证书没有被一个Java信任的证书颁发机构(CA)签发,或者证书链中的某个证书不在Java的信任库中。

解决方案一

我们可以通过在调用HTTPS接口时跳过证书验证的方式处理上述问题。

具体代码

public static String requestIgnoreSSL(String requestUrl,
                                                  String requestMethod, String body, String contentType, Map<String, String> heads)  throws Exception{
        HttpsURLConnection connection;
        StringBuilder buffer = new StringBuilder();
        try {
            // 创建一个信任所有证书的 TrustManager
            TrustManager[] trustManagers = new TrustManager[]{
                    new X509TrustManager() {
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }
                        public void checkClientTrusted(
                                java.security.cert.X509Certificate[] certs, String authType) {
                        }
                        public void checkServerTrusted(
                                java.security.cert.X509Certificate[] certs, String authType) {
                        }
                    }
            };
            // 安装信任所有证书的TrustManager
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustManagers, new java.security.SecureRandom());

            URL url = new URL(requestUrl);
            connection = (HttpsURLConnection) url.openConnection();
            connection.setSSLSocketFactory(sslContext.getSocketFactory());
            // 创建不验证主机名的 HostnameVerifier
            connection.setHostnameVerifier((hostname, session) -> true);

            // 设置请求头属性
            if(heads != null){
                for (Map.Entry<String, String> map : heads.entrySet()) {
                    String key = map.getKey();
                    String value = map.getValue();
                    connection.setRequestProperty(key, value);
                }
            }

            // 设置请求方式
            connection.setRequestMethod(requestMethod);

            if (StrUtil.isNotEmpty(contentType)){
                connection.setRequestProperty("content-type", contentType);
            }
            // 当有数据需要提交时
            if (null != body) {
                OutputStream outputStream = connection.getOutputStream();
                // 设置编码格式,防止中文乱码
                outputStream.write(body.getBytes("UTF-8"));
                outputStream.close();
            }

            // 将返回的输入流转换成字符串
            InputStream inputStream = connection.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(
                    inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(
                    inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 释放资源
            inputStream.close();
            connection.disconnect();
            return buffer.toString();
        } catch (Exception e) {
            throw new Exception(e);
        }
    }

说明:

自定义信任管理器(TrustManager):创建一个X509TrustManager,覆盖验证方法以信任所有证书。

- checkClientTrusted和checkServerTrusted方法留空,跳过证书验证。
- getAcceptedIssuers返回空数组,表示不限制可接受的CA。

配置SSLContext:使用自定义的TrustManager初始化SSLContext。

  • - 使用TLS协议初始化SSLContext。
  • - init方法的第一个参数为null表示不使用客户端证书,第二个参数传入信任所有证书的TrustManager数组。

设置默认的SSL套接字工厂和主机名验证器:替换HttpsURLConnection的默认设置,跳过主机名验证。

  • - 设置HostnameVerifier直接返回true,接受所有主机名。

解决方案二

直接使用Hutool工具提供的 HttpRequest 对象,它会默认跳过 SSL 验证。

具体代码

1、引入依赖

<dependency>
     <groupId>cn.hutool</groupId>
     <artifactId>hutool-all</artifactId>
     <version>5.8.24</version>
</dependency>

2、代码示例:

public static void main(String[] args) throws Exception {
   // GET示例
   System.out.println(HttpRequest.get("https://localhost:8080/testGet/").execute().body());
   
   JSONObject jsonObject = new JSONObject();
   jsonObject.put("username", "admin");
   jsonObject.put("password", "123456"); 
	// POST示例   
   System.out.println(HttpRequest.post("https://localhost:8080/login").body(jsonObject.toString()).execute().body());
}

总结

总的来说,如果程序需要跳过HTTPS证书验证,使用Hutool工具可以用最少最简单的代码达到我们的需求,如果项目中未使用hutool就需要修改我们的代码创建并安装一个信任所有证书的 TrustManager便可解决问题。

在Java应用程序中跳过HTTPS证书验证通常是不推荐的,因为这会削弱应用程序的安全性,使其容易受到中间人攻击。因此跳过HTTPS证书验证仅适用于受控的环境中。推荐使用有效证书,或通过正规CA签发自签名证书,并将证书导入Java信任库(cacerts)来解决问题。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java树形结构递归查询方式

    Java树形结构递归查询方式

    文章介绍了Java中实现树形结构递归查询的方法,首先找出所有的根节点,然后通过循环遍历根节点,找到每个根节点的子节点,最终构建完整的树形结构,这是一种有效的递归查询思路,适用于需要层次化展示数据的场景
    2024-12-12
  • Java foreach相关原理及用法解析

    Java foreach相关原理及用法解析

    这篇文章主要介绍了Java foreach相关原理及用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • Java查询Elasticsearch数据根据指定id检索(in查询)、sql权限过滤、多字段匹配检索及数据排序

    Java查询Elasticsearch数据根据指定id检索(in查询)、sql权限过滤、多字段匹配检索及数据排序

    在Java开发中Elasticsearch(简称ES)是一个非常流行的搜索引擎,它提供了强大的全文搜索和分析功能,这篇文章主要给大家介绍了关于Java查询Elasticsearch数据根据指定id检索(in查询)、sql权限过滤、多字段匹配检索及数据排序的相关资料,需要的朋友可以参考下
    2024-05-05
  • java环境配好后jar文件打开命令框闪退(无打开方式,无反应)解决办法

    java环境配好后jar文件打开命令框闪退(无打开方式,无反应)解决办法

    在Java开发中我们经常会遇到运行Jar包时闪退的问题,下面这篇文章主要给大家介绍了关于java环境配好后jar文件打开命令框闪退(无打开方式,无反应)的解决办法,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2024-04-04
  • springboot跨域过滤器fetch react Response to preflight request doesn‘t pass access control check问题

    springboot跨域过滤器fetch react Response to p

    这篇文章主要介绍了springboot跨域过滤器fetch react Response to preflight request doesn‘t pass access control check问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • Netty粘包拆包问题解决方案

    Netty粘包拆包问题解决方案

    这篇文章主要介绍了Netty粘包拆包问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • Java时间处理详细教程与最佳实践案例

    Java时间处理详细教程与最佳实践案例

    本文系统讲解Java时间处理,涵盖基础概念、传统API(Date/Calendar/SimpleDateFormat)、Java8新API(java.time包)及高级应用,提供代码案例与最佳实践,适合开发者全面掌握时间操作技巧,感兴趣的朋友一起看看吧
    2025-08-08
  • 完美解决Eclipse 项目有红感叹号的问题

    完美解决Eclipse 项目有红感叹号的问题

    下面小编就为大家带来一篇完美解决Eclipse 项目有红感叹号的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • Java实现“年-月-日 上午/下午时:分:秒”的简单代码

    Java实现“年-月-日 上午/下午时:分:秒”的简单代码

    当前的日期输出的方法有很多,本文为大家介绍下在java中是如何实现“年-月-日 上午/下午时:分:秒”,感兴趣的朋友不妨参考下
    2015-08-08
  • SpringBoot Cache 二级缓存的使用

    SpringBoot Cache 二级缓存的使用

    本文主要介绍了SpringBoot Cache 二级缓存的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06

最新评论