The problem which I faced in developing one of application for android want to share with you guys,
My task was to download a .pdf file from a trusted URL in which I need to request to the web server secured with a signed certificate and authenticated URL with some User Name and Password
The problems which I faced step by step are as bellows:-
Problem 1:- I was trying to set up a secure connection via SSL I get a SSL handshake failure when the server requests the certificate.
Solution :- Android: Trusting SSL certificates
after pressing "Get Certifcate" button if certificate is valid then view button will activate by own
Export the certificate from the panel above which will view a file with some extension rename it by "my_certificate.pem"
Create the Keystore
Download the BouncyCastle Provider and store it to a known location.
In Ubuntu I downloaded BouncyCastle using standard command
1- wget http://bouncycastle.org/download/bcprov-jdk16-146.jar
2- keytool -importcert -file my_certificate.pem -keystore yourapp.store -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-jdk16-146.jar -storetype BKS
Put yourapp.store in the “assets” directory of your Android app. Now all you need to do is validate against it. To make a standard HTTPS request:
the block of code need to focus:
URL url = new URL("url from file have to download");
ucon.setConnectTimeout(30000);
String authStr = "UserName" + ":" + "password";
//My .pdf content type
InputStream is = ucon.getInputStream();
I created Contentdownloader AsyncTask for secured connection as per my flexibility for an app modify it as per your need.
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyStore;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.res.AssetManager;
import android.os.AsyncTask;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;
import com.nvison.pdfsignerapp.util.Util;
public class ContentDownloader extends AsyncTask<Boolean, Void, Boolean> {
private static final String TAG = ContentDownloader.class.getSimpleName();
private String directoryLocation;
private String downloadURL;
private String fileName;
private String absolutePath;
private File outputFile;
private ProgressDialog dialog;
private Context context;
private SSLSocketFactory sf;
public ContentDownloader(Context context, String downloadURL, String directoryLocation, String fileName) {
this.context = context;
this.downloadURL = downloadURL;
this.directoryLocation = directoryLocation;
this.fileName = fileName;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
String loadingString = "Downloading pdf...";
dialog = ProgressDialog.show(context, "", loadingString, true);
}
public void download() throws IOException {
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
outputFile = new File(android.os.Environment.getExternalStorageDirectory(), Util.APPLIACTION_ROOT_FOLDER + File.separator
+ directoryLocation);
if (outputFile.exists()) {
return;
}
}
}
@Override
protected Boolean doInBackground(Boolean... params) {
try {
download();
AssetManager assetManager = context.getAssets();
InputStream keyStoreInputStream = assetManager.open("yourapp.store");
KeyStore keyStore = KeyStore.getInstance("BKS");
// password input at a time of generating a keystore using bouncy
keyStore.load(keyStoreInputStream, "password".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
File outputFile = new File(Util.getAppRootFolder(), directoryLocation + File.separator + fileName);
absolutePath = outputFile.getAbsolutePath();
Log.e(TAG, "Absolute path--" + outputFile.getAbsolutePath());
Log.e(TAG, "Saving content----" + downloadURL + "---into---" + directoryLocation);
URL url = new URL(downloadURL);
HttpsURLConnection ucon = (HttpsURLConnection) url.openConnection();
// Authenticator.setDefault(new MyAuthenticator());
ucon.setConnectTimeout(30000);
ucon.setReadTimeout(30000);
ucon.setInstanceFollowRedirects(true);
String authStr = "username" + ":" + "password";
String authEncoded = Base64.encodeToString(authStr.getBytes(), android.util.Base64.NO_WRAP);
ucon.setRequestProperty("Authorization", "Basic " + authEncoded);
ucon.setRequestProperty("Content-Type", "application/octet-stream");
ucon.setSSLSocketFactory(context.getSocketFactory());
ucon.setDoInput(true);
ucon.connect();
Map<String, List<String>> headerFields = ucon.getHeaderFields();
int status = ucon.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
Log.e("TAG", "perfect response code ");
} else {
Log.e("TAG", "Wrong response code ");
}
InputStream is = ucon.getInputStream();
FileOutputStream out = new FileOutputStream(outputFile);
int byteRead = 0;
byte[] buf = new byte[1024];
while ((byteRead = is.read(buf)) != -1) {
out.write(buf, 0, byteRead);
}
out.flush();
out.close();
return true;
} catch (Exception e) {
Log.e(TAG, "Problem while downloading inside doinbackground");
e.printStackTrace();
}
return false;
}
@Override
protected void onPostExecute(Boolean result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (result) {
Toast.makeText(context, "download result--" + result, Toast.LENGTH_SHORT).show();
} else {
Log.e(TAG, "Downloading failed");
}
}
}
My task was to download a .pdf file from a trusted URL in which I need to request to the web server secured with a signed certificate and authenticated URL with some User Name and Password
The problems which I faced step by step are as bellows:-
Problem 1:- I was trying to set up a secure connection via SSL I get a SSL handshake failure when the server requests the certificate.
Solution :- Android: Trusting SSL certificates
- Grab all required certificates (root and any intermediate CA’s)
- Create a keystore with keytool and the BouncyCastle provider and import the certs
- Load the keystore in your android app and use it for the secured connections
after pressing "Get Certifcate" button if certificate is valid then view button will activate by own
Export the certificate from the panel above which will view a file with some extension rename it by "my_certificate.pem"
Create the Keystore
Download the BouncyCastle Provider and store it to a known location.
In Ubuntu I downloaded BouncyCastle using standard command
1- wget http://bouncycastle.org/download/bcprov-jdk16-146.jar
2- keytool -importcert -file my_certificate.pem -keystore yourapp.store -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-jdk16-146.jar -storetype BKS
Put yourapp.store in the “assets” directory of your Android app. Now all you need to do is validate against it. To make a standard HTTPS request:
the block of code need to focus:
AssetManager assetManager = context.getAssets();
InputStream keyStoreInputStream = assetManager.open("yourapp.store");
KeyStore trustStore = KeyStore.getInstance("BKS");
trustStore.load(keyStoreInputStream, "somepass".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
URL url = new URL("url from file have to download");
HttpsURLConnection ucon = (HttpsURLConnection) url.openConnection();
ucon.setConnectTimeout(30000);
ucon.setReadTimeout(30000);
ucon.setInstanceFollowRedirects(true);
//basic header password witht the Url
//Initially I was getting the FilenotFoundException in Inputstream so need to add basic header authentication with he url request
String authStr = "UserName" + ":" + "password";
String authEncoded = Base64.encodeToString(authStr.getBytes(), android.util.Base64.NO_WRAP);
ucon.setRequestProperty("Authorization", "Basic " + authEncoded);
//My .pdf content type
ucon.setRequestProperty("Content-Type", "application/octet-stream");
ucon.setSSLSocketFactory(context.getSocketFactory());
ucon.setDoInput(true);
ucon.connect();
InputStream is = ucon.getInputStream();
FileOutputStream out = new FileOutputStream(outputFile);
int byteRead = 0;
byte[] buf = new byte[1024];
while ((byteRead = is.read(buf)) != -1) {
out.write(buf, 0, byteRead);
}
out.flush();
out.close();
I created Contentdownloader AsyncTask for secured connection as per my flexibility for an app modify it as per your need.
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyStore;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.res.AssetManager;
import android.os.AsyncTask;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;
import com.nvison.pdfsignerapp.util.Util;
public class ContentDownloader extends AsyncTask<Boolean, Void, Boolean> {
private static final String TAG = ContentDownloader.class.getSimpleName();
private String directoryLocation;
private String downloadURL;
private String fileName;
private String absolutePath;
private File outputFile;
private ProgressDialog dialog;
private Context context;
private SSLSocketFactory sf;
public ContentDownloader(Context context, String downloadURL, String directoryLocation, String fileName) {
this.context = context;
this.downloadURL = downloadURL;
this.directoryLocation = directoryLocation;
this.fileName = fileName;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
String loadingString = "Downloading pdf...";
dialog = ProgressDialog.show(context, "", loadingString, true);
}
public void download() throws IOException {
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
outputFile = new File(android.os.Environment.getExternalStorageDirectory(), Util.APPLIACTION_ROOT_FOLDER + File.separator
+ directoryLocation);
if (outputFile.exists()) {
return;
}
}
}
@Override
protected Boolean doInBackground(Boolean... params) {
try {
download();
AssetManager assetManager = context.getAssets();
InputStream keyStoreInputStream = assetManager.open("yourapp.store");
KeyStore keyStore = KeyStore.getInstance("BKS");
// password input at a time of generating a keystore using bouncy
keyStore.load(keyStoreInputStream, "password".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(keyStore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
File outputFile = new File(Util.getAppRootFolder(), directoryLocation + File.separator + fileName);
absolutePath = outputFile.getAbsolutePath();
Log.e(TAG, "Absolute path--" + outputFile.getAbsolutePath());
Log.e(TAG, "Saving content----" + downloadURL + "---into---" + directoryLocation);
URL url = new URL(downloadURL);
HttpsURLConnection ucon = (HttpsURLConnection) url.openConnection();
// Authenticator.setDefault(new MyAuthenticator());
ucon.setConnectTimeout(30000);
ucon.setReadTimeout(30000);
ucon.setInstanceFollowRedirects(true);
String authStr = "username" + ":" + "password";
String authEncoded = Base64.encodeToString(authStr.getBytes(), android.util.Base64.NO_WRAP);
ucon.setRequestProperty("Authorization", "Basic " + authEncoded);
ucon.setRequestProperty("Content-Type", "application/octet-stream");
ucon.setSSLSocketFactory(context.getSocketFactory());
ucon.setDoInput(true);
ucon.connect();
Map<String, List<String>> headerFields = ucon.getHeaderFields();
int status = ucon.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
Log.e("TAG", "perfect response code ");
} else {
Log.e("TAG", "Wrong response code ");
}
InputStream is = ucon.getInputStream();
FileOutputStream out = new FileOutputStream(outputFile);
int byteRead = 0;
byte[] buf = new byte[1024];
while ((byteRead = is.read(buf)) != -1) {
out.write(buf, 0, byteRead);
}
out.flush();
out.close();
return true;
} catch (Exception e) {
Log.e(TAG, "Problem while downloading inside doinbackground");
e.printStackTrace();
}
return false;
}
@Override
protected void onPostExecute(Boolean result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (result) {
Toast.makeText(context, "download result--" + result, Toast.LENGTH_SHORT).show();
} else {
Log.e(TAG, "Downloading failed");
}
}
}
No comments:
Post a Comment