java开发https请求ssl不受信任问题解决方法

yizhihongxing

Java开发HTTPS请求SSL不受信任问题解决方法

在进行Java开发时,我们经常会涉及到请求HTTPS接口的情况。但是,在请求HTTPS接口时,我们有时会遇到SSL证书不受信任的问题,这会导致我们无法正确进行HTTPS请求。本文将详细讲解如何解决Java开发中HTTPS请求SSL不受信任的问题。

问题描述

在使用Java进行HTTPS请求时,如果SSL证书不被当前系统或浏览器所信任,我们会遇到SSL不受信任的错误。例如以下的请求代码:

URL url = new URL("https://example.com");
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.connect();

如果example.com证书不被当前系统或浏览器所信任,上述代码运行时会抛出类似于以下的异常:

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

这意味着SSL请求没有通过,无法访问服务器。

解决方法

方法一:信任指定证书

如果我们知道我们要访问的服务器的证书,我们可以在Java程序中添加该证书并将其信任。这需要我们手动将证书转换为.pem格式,并添加到truststore中。下面是具体的步骤:

  1. 将证书保存到本地,例如保存为example.crt

  2. 使用以下命令将example.crt转换为.pem格式:

openssl x509 -in example.crt -out example.pem -outform PEM
  1. 打开Javacacerts文件,该文件通常位于$JAVA_HOME/jre/lib/security/cacerts

  2. cacerts中添加证书。以下命令可添加证书到cacerts

keytool -importcert -file example.pem -alias example -keystore cacerts

其中,example.pem为上一步转换的.pem证书,example为别名,可以根据自己的需要进行修改,cacerts为Java的truststore

  1. 在Java程序中添加以下代码,启用指定证书的信任:
String cacertsPath = System.getProperty("java.home") + "/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", cacertsPath);
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

其中,cacertsPath为Java的cacerts文件路径,changeit为默认的cacerts密码。

方法二:信任所有证书

如果我们不想手动添加每个需要信任的证书,我们可以在Java程序中添加以下代码,使其信任所有证书:

TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
  public void checkClientTrusted(X509Certificate[] chain, String authType) {
    // do nothing
  }

  public void checkServerTrusted(X509Certificate[] chain, String authType) {
    // do nothing
  }

  public X509Certificate[] getAcceptedIssuers() {
    return new X509Certificate[0];
  }
}};

SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new SecureRandom());

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier((hostname, sslSession) -> true);

上述代码会创建一个TrustManager数组,该数组信任所有证书,然后将其设置为默认的SSLSocketFactory。此外,为了避免主机名验证失败的错误,我们还需要设主机名验证器为所有主机通过。

示例说明

下面是两条示例说明:

示例一:信任指定证书

假设我们要请求的HTTPS接口地址为https://example.com/api,并且我们知道该接口服务器的证书为example.crt。我们可以使用以下代码将其信任:

String cacertsPath = System.getProperty("java.home") + "/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", cacertsPath);
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

KeyStore keyStore = KeyStore.getInstance("JKS");
InputStream inputStream = new FileInputStream("example.crt");
keyStore.load(inputStream, "password".toCharArray());

CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new ByteArrayInputStream(certificate.getBytes());
Certificate ca;
while ((ca = cf.generateCertificate(caInput)) != null) {
  keyStore.setCertificateEntry("example", ca);
}

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier((hostname, sslSession) -> true);

URL url = new URL("https://example.com/api");
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.connect();

上述代码将example.crt信任,并将其添加到Java的truststore中。然后,我们可以使用HttpsURLConnection请求https://example.com/api接口,在请求过程中不会遇到SSL不受信任的错误。

示例二:信任所有证书

如果我们不知道需要请求的HTTPS接口的证书,或者需要避免在添加每个证书时产生的大量工作。我们可以使用以下代码信任所有证书:

TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
  public void checkClientTrusted(X509Certificate[] chain, String authType) {
    // do nothing
  }

  public void checkServerTrusted(X509Certificate[] chain, String authType) {
    // do nothing
  }

  public X509Certificate[] getAcceptedIssuers() {
    return new X509Certificate[0];
  }
}};

SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new SecureRandom());

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier((hostname, sslSession) -> true);

URL url = new URL("https://example.com/api");
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.connect();

上述代码使用了信任所有证书的方法,如果请求的HTTPS接口证书未被信任,则无需进行任何额外工作即可通过请求。

总结

以上就是Java开发中HTTPS请求SSL不受信任问题的解决方法。我们可以信任指定证书或信任所有证书。由于信任所有证书存在一定的安全风险,因此我们应该谨慎使用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java开发https请求ssl不受信任问题解决方法 - Python技术站

(0)
上一篇 2023年6月15日
下一篇 2023年6月15日

相关文章

  • Struts2学习教程之Action类如何访问WEB资源

    为了让Action类能够访问WEB资源,需要进行以下几个步骤: 1. 在struts.xml中进行配置 在struts.xml中需要配置一个<constant>元素,设置resourceBase属性为需要访问的WEB资源的路径。 示例代码: <constant name="struts.convention.result.path…

    Java 2023年5月20日
    00
  • SpringMVC4+MyBatis+SQL Server2014实现数据库读写分离

    下面是关于“SpringMVC4+MyBatis+SQL Server2014实现数据库读写分离”的完整攻略,包含两个示例说明。 SpringMVC4+MyBatis+SQL Server2014实现数据库读写分离 在本文中,我们将介绍如何使用SpringMVC4和MyBatis实现数据库读写分离,以提高系统的性能和可靠性。 步骤1:添加依赖 首先,我们需要…

    Java 2023年5月17日
    00
  • maven仓库repositories和mirrors的配置及区别详解

    介绍 在使用Maven进行依赖管理时,常常会遇到一些有关仓库repositories和镜像mirrors的问题。本文将详细介绍这两个概念及其配置方式和区别。 仓库Repositories 仓库repositories是存储Maven构建的依赖和插件的位置。在Maven中有两种仓库:本地仓库和远程仓库。 本地仓库 指存储在本地计算机上的仓库,一般位于用户的.h…

    Java 2023年5月19日
    00
  • Java详细介绍单例模式的应用

    下面我将为你详细介绍“Java详细介绍单例模式的应用”,这里是完整攻略: 什么是单例模式 单例模式是一种常见的设计模式之一。在该模式中,一个类只能有一个实例,并提供一个全局访问点。 单例模式的应用场景 开发人员经常使用单例模式来控制系统中某些类的唯一性,例如: 数据库连接池 系统配置信息对象 日志记录器对象 单例模式的实现方式 实现单例有两种方式:懒汉式和饿…

    Java 2023年5月26日
    00
  • java中找不到符号的解决方案

    当Java程序在编译时出现“找不到符号”的错误时,通常意味着在代码中引用了一个不存在的类、方法或变量。这种错误通常是由以下几种情况引起的: 类或方法拼写错误 缺少必要的库或包 编译时缺少依赖项 尝试在不正确的作用域中引用变量或方法 下面将为您介绍一些可能的解决方案来解决此类问题。 1.检查拼写错误 如果Java程序在编译时出现“找不到符号”的错误,第一步应该…

    Java 2023年5月20日
    00
  • Spring Integration概述与怎么使用详解

    Spring Integration概述 Spring Integration是Spring框架的一个扩展,提供了一种集成不同系统、应用、协议和数据格式的方式。它提供了许多现成的组件和模板,使得实现企业级集成变得更加便捷和高效。 Spring Integration采用基于消息的异步通信模型,所有的组件都是被设计成异步的最终接收者,而消息则负责在组件之间传递…

    Java 2023年5月19日
    00
  • Spring使用IOC与DI实现完全注解开发

    这里是使用Spring实现完全注解开发的攻略。 什么是IOC与DI? IOC IOC,全称为Inversion of Control,控制反转,是指将业务逻辑控制转移给容器来处理,由容器通过反射机制去创建或调用对象以及处理对象之间的关系,对于容器是重度依赖的。它实现的方式有两种,分别是Setter注入和构造函数注入。 DI DI,全称为Dependency …

    Java 2023年6月2日
    00
  • SpringBoot详解整合Spring Cache实现Redis缓存流程

    让我来详细讲解一下“SpringBoot详解整合Spring Cache实现Redis缓存流程”的完整攻略。 1. Spring Cache 简介 Spring Cache 是 Spring 官方提供的缓存框架,它通过提供 CacheManager 统一管理缓存和缓存操作,屏蔽了不同缓存框架的差异,使得我们只需要处理统一缓存接口即可,极大地降低了使用缓存的难…

    Java 2023年6月15日
    00
合作推广
合作推广
分享本页
返回顶部