Visit a valid https site to see if there will be anything wrong
public static void tryAuthorizedHttps() throws Exception { URL url = new URL("https://www.baidu.com/"); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); InputStream in = conn.getInputStream(); String page = IOUtils.toString(in, "utf8"); System.out.println(page); // successfully printed System.out.println("==================="); //get the first X509 cert on the certificate chain X509Certificate x5Cert = (X509Certificate) conn.getServerCertificates()[0]; System.out.println("Subject:" + x5Cert.getSubjectDN()); // CN = *.baidu.com System.out.println("Issuer:" + x5Cert.getIssuerDN()); // CN = VeriSign in.close(); }
It works because JDK has contained mainstream CA authorities, including VeriSign. You can verify it by
cat $JAVA_HOME/jre/lib/security/cacerts|grep -a VeriSign
Visit a https site with a self-signed certificate to see if there will be anything wrong
public static void trySelfSignedHttps() throws Exception { URL url = new URL("https://some.self.signed.cert.com"); URLConnection conn = url.openConnection(); InputStream in = conn.getInputStream(); // javax.net.ssl.SSLHandshakeException: // unable to find valid certification path to requested target String page = IOUtils.toString(in, "utf8"); System.out.println(page); in.close(); }
You will encounter an SSL related exception since the certificate is self-signed.
P.S. If the site’s certificate is issued by an unknown CA, the same Exception will be thrown with a different exception message.
Add the self-signed certificate on client side and visit the site again
Let the owner of some.self.signed.cert.com pass you their self-signed certificate file. Assume it is named as “cjx_cert.pem”.
Then you can avoid exceptions and still stay in security.
public static void trySelfSignedHttpsWithTrustManager() throws Exception { CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream certInput = StX509Main.class.getResourceAsStream("/examples/x509/cjx_cert.pem"); Certificate cjxCert; try { cjxCert = cf.generateCertificate(certInput); System.out.println("cjxCert=" + ((X509Certificate) cjxCert).getSubjectDN()); } finally { IOUtils.closeQuietly(certInput); } // Create a KeyStore containing the cert String keyStoreType = KeyStore.getDefaultType(); KeyStore trustedKeyStore = KeyStore.getInstance(keyStoreType); trustedKeyStore.load(null, null); trustedKeyStore.setCertificateEntry("cjxCert", cjxCert); // Create a TrustManager that trusts the cert in our KeyStore String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(trustedKeyStore); // Create an SSLContext that uses our TrustManager SSLContext context = SSLContext.getInstance("TLS"); context.init(null, tmf.getTrustManagers(), null); // Tell the URLConnection to use a SocketFactory from our SSLContext URL url = new URL("https://some.self.signed.cert.com"); HttpsURLConnection conn = (HttpsURLConnection)url.openConnection(); conn.setSSLSocketFactory(context.getSocketFactory()); InputStream in = conn.getInputStream(); String page = IOUtils.toString(in, "utf8"); System.out.println(page); in.close(); }