This article mainly discusses the solution to Java development of https request SSL untrusted. The specific analysis and implementation code are as follows.
When requesting https link in java code, the following error may be reported
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
The reason is that there is no certificate. It is OK to use url to access it directly in the browser. The browser should have saved the corresponding .cer certificate before.
There are two solutions: obtaining a valid certificate from the target machine or ignoring the certificate trust issue.
1. Obtain a valid certificate for the target machine
1. Compile and install the certificate program javac InstallCert.java (code as follows)
/* * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are allowed provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclosure in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Sun Microsystems nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *//** * http://blogs.sun.com/andreas/resource/InstallCert.java * Use: * java InstallCert hostname * Example: *% java InstallCert ecc.fedora.redhat.com */import javax.net.ssl.*;import java.io.*;import java.security.KeyStore;import java.security.MessageDigest;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;/** * Class used to add the server's certificate to the KeyStore * with your trusted certificates. */public class InstallCert {public static void main(String[] args) throws Exception {String host;int port;char[] passphrase;if ((args.length == 1) || (args.length == 2)) {String[] c = args[0].split(":");host = c[0];port = (c.length == 1) ? 443 : Integer.parseint(c[1]);String p = (args.length == 1) ? "changeit" : args[1];passphrase = p.toCharArray();} else {System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");return;}File file = new File("jssecacerts");if (file.isFile() == false) {char SEP = File.separatorchar;File dir = new File(System.getProperty("java.home") + SEP + "lib" + SEP + "security");file = new File(dir, "jssecacerts");if (file.isFile() == false) {file = new File(dir, "cacerts");}}System.out.println("Loading KeyStore " + file + "...");InputStream in = new FileInputStream(file);KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());ks.load(in, passphrase);in.close();SSLContext context = SSLContext.getInstance("TLS");TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());tmf.init(ks);X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);context.init(null, new TrustManager[]{tm}, null);SSLSocketFactory factory = context.getSocketFactory();System.out.println("Opening connection to " + host + ":" + port + "...");SSLSocket socket = (SSLSocket) factory.createSocket(host, port);socket.setSoTimeout(10000);try {System.out.println("Starting SSL handshake...");socket.startHandshake();socket.close();System.out.println();System.out.println("No errors, certificate is already trusted");}catch (SSLException e) {System.out.println();e.printStackTrace(System.out);}X509Certificate[] chain = tm.chain;if (chain == null) {System.out.println("Could not obtain server certificate chain");return;}BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));System.out.println();System.out.println("Server sent " + chain.length + " certificate(s):");System.out.println();MessageDigest sha1 = MessageDigest.getInstance("SHA1");MessageDigest md5 = MessageDigest.getInstance("MD5");for (int i = 0; i < chain.length; i++) {X509Certificate cert = chain[i];System.out.println (" " + (i + 1) + " Subject " + cert.getSubjectDN());System.out.println(" Issuer " + cert.getIssuerDN());sha1.update(cert.getEncoded());System.out.println(" sha1 " + toHexString(sha1.digest()));md5.update(cert.getEncoded());System.out.println(" md5 " + toHexString(md5.digest()));System.out.println();}System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");String line = reader.readLine().trim();int k;try {k = (line.length() == 0) ? 0 : Integer.parseint(line) - 1;}catch (NumberFormatException e) {System.out.println("KeyStore not changed");return;}X509Certificate cert = chain[k];String alias = host + "-" + (k + 1);ks.setCertificateEntry(alias, cert);OutputStream out = new FileOutputStream("jssecacerts");ks.store(out, passphrase);out.close();System.out.println();System.out.println(cert);System.out.println();System.out.println();System.out.println();System.out.println ("Added certificate to keystore 'jssecacerts' using alias '" + alias + "'");}private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();private static String toHexString(byte[] bytes) {StringBuilder sb = new StringBuilder(bytes.length * 3);for (int b : bytes) {b &= 0xff;sb.append(HEXDIGITS[b >> 4]);sb.append(HEXDIGITS[b & 15]);sb.append(' ');}return sb.toString();}private static class SavingTrustManager implements X509TrustManager {private final X509TrustManager tm;private X509Certificate[] chain;SavingTrustManager(X509TrustManager tm) {this.tm = tm;}public X509Certificate[] getAcceptedIssuers() {throw new UnsupportedOperationException();}public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {throw new UnsupportedOperationException();}public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {this.chain = chain;tm.checkServerTrusted(chain, authType);}}} 2. Run the installation certificate program to generate a certificate
java InstallCert my.hoolai.com
For example: java InstalCert smtp.zhangsan.com:465 admin If the password and host port number are not added, the default port number given in the above certificate obtaining program is: 443, and the password is: changeit
3. According to the operation prompt information, enter 1 and enter, and generate a certificate named: jssecacerts in the current directory.
Place the certificate in the $JAVA_HOME/jre/lib/security directory, remember that the jre of the JDK is the environment used by the project! ! !
or:
System.setProperty("javax.net.ssl.trustStore", "你的jssecacerts证书路径");
You can change the password and run the command in the security directory
keytool -storepasswd -new xxxcom -keystore cacerts
You can modify the password and use the command after modifying it
keytool -list -v -keystore cacerts
When viewing the information of the file, it will prompt that you need a password to view it. If the input password matches the modified password, it means that the modification has been successful.
PS: At this point, you can successfully use ssl. In addition, based on the file jssecacerts generated just now, you can generate a cer file.
The command is as follows
keytool -export -alias xxx.com-1 -keystore jssecacerts -rfc -file xxx.cer
As mentioned above, the default naming alias in the previous tool class was to add "-1". The password set using InstallCert must be the same as the password in the cacherts file.
If you have modified the password, you need to modify the corresponding password string in the InstallCert class, otherwise the following exception will be:
java.security.UnrecoverableKeyException: Password verification failed
2. Ignore the certificate trust issue
Source code: http://mengyang.iteye.com/blog/575671
Be sure to note that you need to call the methods described in the article before the connection is created, like this:
trustAllHttpsCertificates();HostnameVerifier hv = new HostnameVerifier() { public boolean verify(String urlHostName, SSLSession session) { return true; } };HttpsURLConnection.setDefaultHostnameVerifier(hv);connection = (HttpURLConnection) url.openConnection();OK, both methods have been tried and worked.
Summarize
The above is the entire content of this article about the solution to the problem of untrusted https request SSL in Java. I hope it will be helpful to everyone. Interested friends can continue to refer to other related topics on this site. If there are any shortcomings, please leave a message to point it out. Thank you friends for your support for this site!