报错 | PKIX path building failed: ...SunCertPathBuilderException:unable to find valid certification...


01 Problem Scenario

When accessing an untrusted HTTPS website in Java, an error message will be prompted:

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Translated into Chinese is:

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: Unable to find a valid certification path for the requested target.

This is because the default trust certificate of the JVM (Java Virtual Machine) does not contain the SSL certificate of the target website, resulting in the inability to establish an effective trust chain.

02 Analyze the problem

The JVM itself maintains a default trust certificate, which is a file without a suffix name. The file name cacertsis located in the java installation path, for example:

C:\Program Files\Java\jdk-17\lib\security\cacerts

When Java accesses an https website, this exception usually does not occur. However, for some https websites, due to various reasons, there is a problem that the certificate is not trusted. When accessing using a browser, the following interface will appear:

Insert image description here
Java will cause an error when accessing such a website.

03 Three solutions

After some searching, I found solutions online:

  1. Trust all SSL certificates
    . Reference: https://developer.aliyun.com/article/812846
    This solution is a solution, but in addition to security issues, it will also cause intrusion into the code and is not easy to integrate in framework projects.

  2. Add the untrusted certificate to the JVM default trust certificate.
    Reference: https://www.cnblogs.com/qixing/p/11883494.html
    This solution avoids the problem of code intrusion, but it comes with the need to modify the default files that come with java. It is somewhat inappropriate to manually add an untrusted certificate, and you may forget to restore or back up the original default file after adding it.

  3. Generate certificates for untrusted websites separately and specify them in the project.
    This is also the solution used in this article, which avoids the problems of the above two solutions.

04 Solution steps

4.1 Obtain the SSL certificate of the target website

Because I am visiting my own website, and as the webmaster, I have my own certificate, so it does not involve the problem of obtaining the certificate of the target website. If I need to obtain it, it is not difficult. I can just click the icon in the upper left corner of the browser page to export it. (You can search it on Baidu yourself). After exporting, it is usually a file .crtor .pemfile.

4.2 Create a Java trust store

Create a Java truststore (Truststore) and import the SSL certificate of the target website into it. Use the command line tool that comes with Java keytoolto complete this operation. Use command in cmd:

keytool -import -keystore <信任库文件路径> -storepass <密码> -alias alias_for_certificate -file <证书文件路径>

This command consists of 4 parts:
keytool -importCommand for import
-keystore <信任库文件路径>The trust store file you want to generate, for example, the path can be written: C:\Users\abc\Desktop\truststore.jks
-storepass <密码>Set a trust store password
-alias alias_for_certificate -file <证书文件路径>Specify the certificate file to be imported, for example You can write: C:\Users\abc\Desktop\cert.pem

4.3 Tell the JVM to use the trust store

In your Java application, tell the JVM to use the trust store you just created. Cause the JVM to load this truststore at runtime.
This is accomplished by setting the following system properties:

System.setProperty("javax.net.ssl.trustStore", "<信任库文件路径>");	// 刚才填写的路径
System.setProperty("javax.net.ssl.trustStorePassword", "<密码>");	// 刚才填写的密码

This problem is solved!

05 Supplement

5.1 Solution to command line prompt without keytool

It is usually caused by jdk not adding environment variables. You can add environment variables and try again, or directly cd to the path where keytool is located to execute the command. For example, my keytool tool is stored in: C:\Program Files\Java\jdk-17\ bin directory.

5.2 How to specify the trust store in SpringBoot project

Just put the above two lines of code where SpringApplication.run() is located. Example:

@SpringBootApplication
public class DemoApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(DemoApplication.class, args);
        // 代码放到这里 可以使用相对路径
        System.setProperty("javax.net.ssl.trustStore", "C:\\Users\\truststore.jks");
        System.setProperty("javax.net.ssl.trustStorePassword", "123456");
    }
}

Guess you like

Origin blog.csdn.net/xuzhongyi103/article/details/131515281