Increase performance of a HttpsURLConnection, getInputStream() very slow - java

This is basically how I am reading the content from an URL and get the content in the variable result. The result is a json parsed after.
I was wondering if it was a way to increase the performance of this request as it takes up to 4~5 seconds while I would like it to take, if possible, less than 2.
Thing is trustAllHosts() and BufferedReader br = new BufferedReader(new InputStreamReader(in)); seems to take some time, but I'm not sure about that. Any idea will be appreciated!
try {
URL url;
// get URL content
url = new URL(apiURL);
trustAllHosts();
conn = (HttpsURLConnection) url.openConnection();
conn.setHostnameVerifier(DO_NOT_VERIFY);
conn.setRequestMethod("GET");
conn.setRequestProperty("some values here");
conn.setConnectTimeout(10000);
in=conn.getInputStream();
// open the stream and put it into BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(in));
while ((line=br.readLine())!= null) {
builder.append(line);
}
result=builder.toString();
//System.out.print(result);
br.close();
} catch (MalformedURLException e) {
result=null;
} catch (java.net.SocketTimeoutException e) {
result=null;
} catch (IOException e) {
result=null;
}
catch (Exception e) {
result=null;
}
finally {
try {
in.close();
}catch(Exception e){}
try {
conn.disconnect();
}catch(Exception e){}
return result;
}
trustAllHosts() :
/**
* Trust every server - dont check for any certificate
*/
private static void trustAllHosts() {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
}
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
} };
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}

Related

Java - gz archive downloaded as octet stream

I'm encountering a problem while downloading a gzip file and saving it in the file system with Java 5. When the download is finished, the file (which has the correct name and extension) appears to have a different MIME type... I'm unable to unzip it from my Linux server (using gunzip) and if I try to open it with WinZip on my Windows pc I see a "recursive" archive (like a matryoshka doll). If I type the command file *filename*.gz from the server, it recognizes the file as an ascii text.
Instead, if I try to download the archive using the browser, everything goes well and I can correctly open and unzip the file (even with my Linux server) and now it's recognized as a gzip compressed archive.
Here's the code I'm using to download the file and save it.
Main.java:
public class Main {
public static void main(String[] args) {
String filePath = "";
HttpOutgoingCall httpOngoingCall = null;
httpOngoingCall = new HttpOutgoingCall();
String endpointUrl = "https://myurl/myfile.gz";
try {
InputStream inputStream = httpOngoingCall.callHttps(endpointUrl);
//I also tried with ZipInputStream and GZIPInputStream
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
filePath = parseAndWriteResponse(br, "myfile.gz", "C:\\");
System.out.println(filePath);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
private static String parseAndWriteResponse(BufferedReader br, String fileName,
String destPath) {
String outputFileName = null;
outputFileName = destPath + File.separator + fileName;
String line;
File outputFile = new File(outputFileName);
FileWriter fileWriter = null;
BufferedWriter bw = null;
try {
if (!outputFile.exists()) {
outputFile.createNewFile();
}
} catch (IOException e1) {
}
try {
fileWriter = new FileWriter(outputFile);
bw = new BufferedWriter(fileWriter);
while ((line = br.readLine()) != null) {
bw.write(line);
bw.write("\n");
}
} catch (IOException e) {
} finally {
try {
bw.close();
fileWriter.close();
} catch (IOException e) {
}
}
return outputFileName;
}
HttpOutgoingCall.java:
public class HttpOutgoingCall {
private InputStream inStream = null;
private HttpsURLConnection httpsConnection = null;
private final static int CONNECTION_TIMEOUT = 20000;
public InputStream callHttps(String endpointUrl) throws Exception {
String socksServer = "";
String socksPort = "";
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
Properties properties = System.getProperties();
System.setProperty("java.protocol.handler.pkgs", "javax.net.ssl");
java.security.Security
.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
if (!socksServer.equals("")) {
if (System.getProperty("socksProxyHost") == null) {
properties.put("socksProxyHost", socksServer);
}
if (!socksPort.equals("")) {
if (System.getProperty("socksProxyPort") == null) {
properties.put("socksProxyPort", socksPort);
}
}
}
System.setProperties(properties);
System.setProperty("java.protocol.handler.pkgs", "javax.net.ssl");
java.security.Security
.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
} };
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
httpsConnection = (HttpsURLConnection) (new URL(endpointUrl)).openConnection();
httpsConnection.setDoOutput(true);
httpsConnection.setUseCaches(false);
httpsConnection.setConnectTimeout(CONNECTION_TIMEOUT);
httpsConnection.setReadTimeout(CONNECTION_TIMEOUT);
inStream = httpsConnection.getInputStream();
} catch (Exception e) {}
return inStream;
}
Could someone help me? Thanks!
When writing your file, you should send it through a java.util.zip.GZIPOutputStream.

java.io.FileNotFoundException: while accessing REST service

I'm trying to access a web service through REST API post method and end up with FileNotFoundException
code:
public class TestService {
static {
disableSSLVerification();
}
public static void main(String[] args) {
String[] names = {"login","seq","password"};
String[] values = { "admin", "2811", "admin" };
String url = "https://localhost:8844/login";
try {
httpPost(url, names, values);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String httpPost(String urlStr, String[] paramName, String[] paramVal) throws Exception {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setAllowUserInteraction(false);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStream out = conn.getOutputStream();
Writer writer = new OutputStreamWriter(out, "UTF-8");
for (int i = 0; i < paramName.length; i++) {
writer.write(paramName[i]);
writer.write("=");
writer.write(URLEncoder.encode(paramVal[i], "UTF-8"));
writer.write("&");
}
System.out.println("WRITER: " + writer);
writer.close();
out.close();
if (conn.getResponseCode() != 200) {
throw new IOException(conn.getResponseMessage());
}
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
rd.close();
conn.disconnect();
return sb.toString();
}
public static void disableSSLVerification() {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
SSLContext sc = null;
try {
sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}
}
Log:
java.io.FileNotFoundException: https://localhost:8844/login
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown S
ource)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown So
urce)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unkn
own Source)
can anyone please help me to resolve this? please try to help me rather marking this one 'duplicate'.
It's actually an HttpsURLConnection (you are opening a https:// url).
That URL does not exist, try opening it in your browser. If the url exists it could be that you are using a self-signed certificate on that https host, that is rejected by java urlconnection classes(but i don't think that's the case, the exception should be different, in that case you'll need to implement a wrapper that accept the certificate anyway).
You may try removing:
conn.setDoOutput(true);
conn.setDoInput(true);
since response was not received because there's the problem with the method signature. it has been updated. I have changed accordingly and now it is working fine.
String[] names = {"username","password"};
String[] values = { "admin", "admin" };
String url = "https://localhost:8844/session";

Android SSL HostName Was Not Verified

I have a self signed server hardcoded port 52428. My client app keeps getting "Hostname Was Not Verified" even when I override the HostNameVerifier to always return true. When I changed the hostname from IP Address to DNS, another error pops up that says "Unable to resolve host: No Address associated with hostname"
Here's my code:
private class SSLConnect extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... values) {
//String https_url = "https://www.google.com/";
//String https_url = "https://192.168.0.106:52428/webserveradmin/preferences";
String https_url = "https://home-pc:52428/webserveradmin/preferences/";
String response;
try {
TrustManager[] tm = new TrustManager[]{
new X509TrustManager() {
#Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public X509Certificate[] getAcceptedIssuers() {
//return new X509Certificate[0];
return null;
}
}
};
URL url;
try {
url = new URL(https_url);
}
catch (MalformedURLException e) {
return "Error URL: " + e.getMessage();
}
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
try {
conn.setDefaultHostnameVerifier(new NullHostNameVerifier());
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, tm, new SecureRandom());
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization", "Basic " + Base64.encode("sa:sa".getBytes(), Base64.DEFAULT));
conn.connect();
InputStream in = conn.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(in));
StringBuilder sb = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
sb.append(line);
}
response = sb.toString();
} catch (GeneralSecurityException e) {
return "Error Security: " + e.getMessage();
}
}
catch(Exception e){
return "Error SSL: " + e.getMessage();
}
return response;
}
#Override
protected void onProgressUpdate(Void... values) {
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(ctxt, result, Toast.LENGTH_LONG).show();
}
}
public class NullHostNameVerifier implements HostnameVerifier{
#Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
The hostname verifier cares about verifying the hostname only, not the trust chain. But with self-signed certificates you don't have a trust chain leading to a locally trusted certificate.
Apart from that, just disabling the certificate checking is a very bad idea, because this way you will not only accept your self-signed certificate but instead any certificates and thus you will be open to man-in-the-middle attacks. See also SSL Vulnerability in ******** VU#582497.
To do it correctly use instead certificate/public key pinning. For a more detailed explanation and also sample code see OWSAP.

Android Hostname was not be verified. How to allow all hosts?

I am trying to get an image from a URL which starts with HTTPS. I keep getting the Hostname was not verified exception.
I took a look at this question java.io.IOException: Hostname was not verified but didn't understood how to make it work.
Is there any way I can allow all hostnames?
Here's the code thats giving me trouble:
public Drawable drawableFromUrl(String url) {
Bitmap x;
HttpURLConnection connection;
try {
connection = (HttpURLConnection) new URL(url).openConnection();
connection.connect();
InputStream input = connection.getInputStream();
x = BitmapFactory.decodeStream(input);
return new BitmapDrawable(x);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
return null;
}
return null;
}
Thanks in advance for your help
This error occurs when the TLS certificate is either self-signed or the domain on the certificate doesn't match the server's host name.
This answer provides a complete solution:
/**
* Disables the SSL certificate checking for new instances of {#link HttpsURLConnection} This has been created to
* aid testing on a local box, not for use on production.
*/
private static void disableSSLCertificateChecking() {
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
#Override
public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
// not implemented
}
#Override
public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
// not implemented
}
#Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
}
};
try {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
Simply run that once at any time before making your first HTTPS connection. If you control the server, though, it is strongly preferred to try and obtain a valid certificate instead.

Return code 403 while reading URL with HttpsURLConnection

I am trying to read the content of the URL with the code down below, but get an 403 error:
https://api.kraken.com/0/public/Time
The URL is reachable in the Problem or via Rest-Connection-Test-Pages like https://apigee.com without a problem. The code works for other HTTPS-Urls just fine. I have no clue what could be wrong here:
public class HttpsClient{
public static void main(String[] args)
{
new HttpsClient().testIt();
}
private void testIt(){
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
;
}
String https_url = "https://api.kraken.com/0/public/Time";
URL url;
HttpsURLConnection con = null;
try {
url = new URL(https_url);
con = (HttpsURLConnection)url.openConnection();
//dumpl all cert info
print_https_cert(con);
try{
System.out.println("****** Content of the URL ********");
BufferedReader br =
new BufferedReader(
new InputStreamReader(con.getInputStream()));
String input;
while ((input = br.readLine()) != null){
System.out.println(input);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager(){
#Override
public X509Certificate[] getAcceptedIssuers(){return null;}
#Override
public void checkClientTrusted(X509Certificate[] certs, String authType){}
#Override
public void checkServerTrusted(X509Certificate[] certs, String authType){}
}};
}

Categories