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

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日

相关文章

  • spring boot与spring mvc的区别及功能介绍

    区别: Spring Boot和Spring MVC都是Spring框架的一部分。Spring MVC是一种基于MVC(Model-View-Controller)的Web框架,用于构建Web应用程序,而Spring Boot则是一个用于简化Spring应用程序开发的框架,它可以在开发过程中自动配置和管理一些常见的Spring功能,而无需进行手动配置。因此,…

    Java 2023年5月15日
    00
  • Java基于Scanner对象的简单输入计算功能示例

    Java基于Scanner对象的简单输入计算功能示例是一种常见的Java实践方法,可以帮助初学者快速掌握Java语言输入计算的基本功能。下面,我将详细讲解这种方法的攻略步骤和示例用法。 准备开发环境 首先,你需要安装一个Java开发环境,并创建一个Java项目。例如,可以使用Java SE Development Kit 8,和Eclipse开发工具。 导入…

    Java 2023年5月26日
    00
  • java多线程学习笔记之自定义线程池

    Java多线程学习笔记之自定义线程池 什么是线程池 线程池是管理线程的一种机制。在Java中,可以通过Executor接口及其实现类来创建线程池。线程池的主要作用是优化线程的创建和运行过程。通过创建线程池,可以减少线程创建的开销,并且可以更好地控制线程的运行状态。 创建线程池 基本使用 Java中提供了四种线程池的实现类,它们分别为: newFixedThr…

    Java 2023年5月19日
    00
  • Java读取数据库表(二)

    Java读取数据库表(二) application.properties db.driver.name=com.mysql.cj.jdbc.Driver db.url=jdbc:mysql://localhost:3306/easycrud?useUnicode=true&characterEncoding=utf8&serverTimezo…

    Java 2023年5月4日
    00
  • java编程的30个建议

    “Java编程的30个建议”攻略 简介 “Java编程的30个建议”是一本由石凡等人撰写的关于Java编程的指南书籍。该书籍通过30个不同的示例,介绍了Java编程中的一些基本原则和技巧。本攻略将会对该书籍的内容进行详细解读和说明。 建议1:理解Java堆栈模型 Java堆栈模型是整个Java程序的基础架构。程序中的所有变量、对象都被保存在堆和栈中。灵活的使…

    Java 2023年5月30日
    00
  • mybatis分页效果实现代码

    下面我来详细讲解一下mybatis分页效果实现代码的完整攻略。 什么是mybatis分页? mybatis分页是指将查询出来的结果集分成一定数量的小部分,每次只显示其中的一部分,以此来获得更加良好的用户体验。在使用mybatis进行开发时,我们可以利用一些已有的插件或者自定义代码来实现mybatis分页。 基于插件实现mybatis分页 在mybatis中,…

    Java 2023年5月20日
    00
  • Java NIO实现群聊系统

    Java NIO实现群聊系统攻略 1. 概述 Java NIO(New I/O)是Java 1.4版本引入的新的I/O模型,与之前的I/O模型(阻塞式I/O)不同,Java NIO使用了非阻塞I/O模型。在Java NIO中,所有的I/O操作都是异步的,即非阻塞的。 Java NIO实现群聊系统,可以使用Java NIO的SocketChannel和Sele…

    Java 2023年5月30日
    00
  • 探讨Java中最常见的十道面试题(超经典)

    让我来为你详细讲解“探讨Java中最常见的十道面试题(超经典)”的完整攻略。 前言 在面试Java相关职位时,经常会被问到一些非常经典的问题。本文将列举出Java中最常见的十道面试题,并为每个问题提供完整的解答,希望能够帮助你在面试时取得更好的成绩。 面试题1:Java中的“值传递”和“引用传递”有何区别? 在Java中,所有的参数传递都是“值传递”,也就是…

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