Sunday, 20 November 2016

java - how to Authenticate using HttpURLconnection



i'm trying to read a website as html using the following code(i.e < html >< body >.....< /body >< /html >, but i need to provide authentication credentials, i have tried providing using java.net.Authenticator but it still dosen't seem to work, (if i enter www.google.com it works since no authentication is required)(I wish to implement this code in my android application)



package com.test.connection;


import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Authenticator;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.net.HttpURLConnection;


public class Authenticate {

String username="myuser";
String password="mypass";
URL url=null;
String webHtmlData=null;

public static void main(String[] args) {
Authenticate au=new Authenticate();

au.setConnectionToWS("https://mysite/New/"); //if i enter www.google.com it works

}

public void setConnectionToWS(String inpUrl){

Authenticator myAuth = new Authenticator()
{
@Override
protected PasswordAuthentication getPasswordAuthentication()

{
return new PasswordAuthentication(username, password.toCharArray());
}
};

Authenticator.setDefault(myAuth);

try {
url = new URL(inpUrl);
} catch (MalformedURLException e) {

e.printStackTrace();
}
HttpURLConnection urlConnection = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();//on debugging the code fails on this line.
} catch (IOException e) {
e.printStackTrace();
}
try {

InputStream in = null;
try {
in = new BufferedInputStream(urlConnection.getInputStream());

} catch (IOException e) {
e.printStackTrace();
}
}
finally {
webHtmlData=readStream(urlConnection);

System.out.println(webHtmlData);
System.out.println("Done!!!");

}
}

//read data as a browser
private String readStream(HttpURLConnection urlConnection) {

StringBuffer response = null;


try {
BufferedReader is =
new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String inputLine;
response = new StringBuffer();
while ((inputLine = is.readLine()) != null) {
response.append(inputLine);
}
is.close();

}
catch (Exception e) {
e.printStackTrace();
}
return response.toString();
}


}




i tried debugging and the code shows the following error at line urlConnection.connect()



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(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)

at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(Unknown Source)
at com.test.connection.Authenticate.setConnectionToWS(Authenticate.java:48)
at com.test.connection.Authenticate.main(Authenticate.java:23)

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(Unknown Source)
at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
at sun.security.validator.Validator.validate(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
... 13 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)

at java.security.cert.CertPathBuilder.build(Unknown Source)
... 19 more


Am i not providing the credentials properly???



on passing the url as www.google.com i get the output as



Google



 

Advanced searchLanguage tools




© 2013 - Privacy & Terms


Done!!!



i need to get the same on passing my url which requires authentication,(on entering my url on a browser a popup is shown to enter username and password which on submitting i am directed to the page)


Answer



If you have a self-signed certificate, either you should import your self-signed certificate into java truststore or easy way add below code to bypass certificate validation. In production it is better to use a trusted certificate.



Add following code after Authenticator.setDefault(myAuth); line.



// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {

@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}

@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}

@Override

public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};

// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;

}
};

try {
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

} catch (Exception ex) {
ex.printStackTrace();
}


Finally change this line



urlConnection = (HttpURLConnection) url.openConnection();



to (use HttpsUrlConnection)



urlConnection = (HttpsURLConnection) url.openConnection();

No comments:

Post a Comment

c++ - Does curly brackets matter for empty constructor?

Those brackets declare an empty, inline constructor. In that case, with them, the constructor does exist, it merely does nothing more than t...