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日

相关文章

  • WIN2003上Apache2+IIS6+Tomcat5之多站点完美配置篇

    接下来我将为你详细讲解“WIN2003上Apache2+IIS6+Tomcat5之多站点完美配置篇”的完整攻略。 什么是Apache,IIS以及Tomcat Apache Apache是一款常用的Web服务器软件,支持多种操作系统和编程语言。它是自由软件,采用了Apache许可证,因此可以免费使用、复制、修改和分发。Apache的优点是简单易用、配置灵活、性…

    Java 2023年5月19日
    00
  • Java多线程CountDownLatch的实现

    下面是我对于“Java多线程CountDownLatch的实现”的完整攻略。 CountDownLatch简介 CountDownLatch是JavaSE5中并发包(java.util.concurrent)中的一个类,它可以允许一个线程等待一组线程完成操作后再继续执行。 具体来说,CountDownLatch 常用于某个线程需要等待其它线程执行完毕某些操作…

    Java 2023年5月18日
    00
  • Java程序命令行参数用法总结

    Java程序命令行参数用法总结 Java程序启动时可以传递命令行参数,这些参数会被Java虚拟机解析并传递给main方法。在程序中可以通过args参数获取到传递的命令行参数。本文将介绍Java程序命令行参数的用法。 获取命令行参数 Java程序获取命令行参数非常简单,只需在main方法的参数列表中添加一个String数组类型的参数即可。例如: public …

    Java 2023年5月23日
    00
  • jsp-解决文件上传后重启Tomcat时文件自动删除问题

    当使用Java Servlet和JSP技术接收文件上传时,有时候文件会在重启Tomcat服务器后自动删除,这种现象在Tomcat的上下文被卸载并重新加载时会发生。这个问题可以通过修改Tomcat的配置文件,或更改文件上传时的目录路径来解决。接下来,将详细讲解如何解决这个问题。 方案一:修改Tomcat的配置文件 打开Tomcat的conf/server.xm…

    Java 2023年6月15日
    00
  • 性能优化包括哪些方面?

    以下是关于性能优化包括哪些方面的完整使用攻略: 性能优化包括哪些方面? 性能优化是指通过改进程序的设计、算法、数据结构、代码实现等方面,提高程序的运行效率和响应速度,减少资源占用和延迟等问题。性能优化包括以下几个方面: 1. 程序设计 程序设计是性能优化的重要方面之一。在程序设计阶段,需要考虑程序的整体架构、模块划分、接口设计等方面,从而保证程序的可扩展性、…

    Java 2023年5月12日
    00
  • Java实现把两个数组合并为一个的方法总结

    针对“Java实现把两个数组合并为一个的方法总结”,我为您提供以下完整攻略。 1. 使用concat方法合并数组 Java提供了一个非常简单的函数concat来合并两个数组。但是,这种方法只适用于元素类型相同的数组。 具体操作步骤: 初始化两个需要合并的数组; 分别使用Arrays类的toString()方法将两个数组转换为字符串形式; 使用Arrays类的…

    Java 2023年5月26日
    00
  • SpringBoot SSMP 整合案例分享

    SpringBoot SSMP整合案例分享 SpringBoot是一个快速开发框架,SSM是一个经典的JavaWeb开发框架,它们的整合可以让我们更加高效地进行JavaWeb开发。本文将分享一个SpringBoot整合SSM的案例,包括如何整合MyBatis和SpringMVC,并提供两个示例说明。 1. 创建SpringBoot项目 首先,我们需要创建一个…

    Java 2023年5月18日
    00
  • Java+Redis撤销重做功能实现

    针对“Java+Redis撤销重做功能实现”的攻略,我们可以按照以下步骤进行: 一、概述 撤销和重做是一个常见的功能,可以提高用户的使用体验。在实现撤销重做功能时,我们可以利用 Redis 的数据结构,使用栈来实现。 二、具体实现 1. 初始化栈 首先,我们需要初始化两个栈,一个用来存储撤销操作的数据,一个用来存储重做操作的数据。初始化栈的实现代码如下所示:…

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