Basic authentication with HTTPS
I'm currently trying to access a URL with both HTTP and HTTPS. The URL that I'm trying to access requires basic authentication. With HTTP it works fine, but with HTTPS it doesn't. I'm not sure if there's anything I need to add differently with HTTPS. The URL is supposed to return to me text that is in key value format that I can load into a Properties
Object.
Here is the code I have tried so far.
if (cpUrl.getProtocol().equals("https")) {
out.println("https", 0);
HttpsURLConnection connection = (HttpsURLConnection) cpUrl.openConnection();
TrustManager[] trustAllCerts = new TrustManager[] { new BusinessIntelligenceX509TrustManager() };
SSLContext sc;
try {
sc = SSLContext.getInstance("SSL");
}
catch (NoSuchAlgorithmException noSuchAlgorithmException) {
return;
}
HostnameVerifier hv = new BusinessIntelligenceHostnameVerifier();
try {
sc.init(null, trustAllCerts, new java.security.SecureRandom());
}
catch (KeyManagementException keyManagementException) {
return;
}
HttpsURLConn开发者_如何学JAVAection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(hv);
connection.setDoInput(true);
connection.setRequestProperty("Authorization", "Basic " + encode);
connection.setRequestMethod("POST");
connection.connect();
stream = connection.getInputStream();
Properties properties = new Properties();
properties.load(stream);
}
Here are the certificate classes
//HTTPS CERTIFICATE CLASSES
class BusinessIntelligenceHostnameVerifier implements HostnameVerifier {
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
}
class BusinessIntelligenceX509TrustManager implements X509TrustManager {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
// no-op
}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
// no-op
}
}
The error message when I remove all the certificate code (as well as with the certificate code):
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
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1518)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:848)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:818)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1030)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1057)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1041)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:402)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:170)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:133)
at com.tecsys.bi.install.BiInstall2ControlPanelPromptsProcessor.run(BiInstall2ControlPanelPromptsProcessor.java:117)
at java.lang.Thread.run(Thread.java:595)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:221)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:145)
at sun.security.validator.Validator.validate(Validator.java:203)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:172)
at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(SSLContextImpl.java:320)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:841)
... 12 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:236)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:194)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:216)
... 17 more
The problem appears to be with the fact that the connection is opened, before the SSLContext
and HostNameVerifier
instances are changed for the connection. This is not possible, for the SSL/TLS handshake occurs even before the contents of the connection are read from an InputStream
.
In other words, the following line
HttpsURLConnection connection = (HttpsURLConnection) cpUrl.openConnection();
ought to execute only after the SSLContext
and HostNameVerifier
s instances have been registered with the HttpsURLConnection
class.
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(hv);
Fixing this sequence, ought to fix the problem, for the handshake will now occur using the new parameters.
精彩评论