开发者

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 HostNameVerifiers 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜