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();
}