Background
Android supports the java.net and org.apache packages to access Web Services. I use Apache packages as I find them more useful and easier than using Java packages.
System Requirements
* Bouncy Castle
To Start
Host and Peer Verification are shown here. Each Android application has its own trusted store called KeyStore. In the KeyStore, we can store our self-signed SSL certificates that will be used for the verification purposes of our Web Service. Android trusts a couple of Trust Certificates, but if our signed certificate is not signed among those, then we need to add our certificate to the trusted store of the application.
Assuming you already have a self-signed certificate (if not, kindly use the key tool of Java to create one), let's add the certificate to a keystore using Bouncy Castle that we can access in our application. Like keytool is used in Java to create certificates, Bouncy Castle is the only way to add certificates to the Android keystore.
1. Creating the KeyStore
Download and unzip Bouncy Castle in a proper location and add the .jar file to the class path. Open cmd, go to the application folder, and type the following command:
Collapse
keytool -import -v -trustcacerts -alias 0 -file mycertificate.crt
-keystore res/raw/mystore.bks -storetype BKS -provider
org.bouncycastle.jce.provider.BouncyCastleProvider -storepass mypassword
* file parameter points to your certificate file that you want to add
* keystore => gives the store name that you want to give
* storepass => password to access the keystore
On successful execution of the command, the mystore.bks file will be generated successfully.
2. Create a Class to Use Our Store for HTTPS Connections
To use the store that we created above, we have to create a custom Apache DefaultHttpClient that knows to use the store for HTTPS requests.
Collapse
public class MyHttpClient extends DefaultHttpClient {
final Context context;
public MyHttpClient(Context context) {
this.context = context;
}
@Override
protected ClientConnectionManager createClientConnectionManager {
SchemeRegistry registry = new SchemeRegistry();
registry.register("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register("https", newSslSocketFactory(), 443));
return new SingleClientConnManager(getParams(), registry);
}
private SSLSocketFactory newSslSocketFactory() {
try {
KeyStore trusted = KeyStore.getInstance("BKS");
InputStream in = context.getResources().openRawResource(R.raw.mystore);
try {
trusted.load(in, "mypassword".toCharArray());
}
finally {
in.close();
}
SSLSocketFactory mySslFact = new SslFactory(trusted);
//mySslFact.setHostNameVerifier(new MyHstNameVerifier());
return mySslFact;
} catch(Exception e) {
throw new AssertionError(e);
}
}
}
This code helps us to accept a server certificate and sets the certificate for verification. You can see how we are using our -storename parameter "BKS" to get the instance of the KeyStore, loading the certificate file mystore from R.raw, and setting its password that was used while adding it to the store.
3. Copy mystore File
Import the generated mystore.bks file to the res/raw folder. So our above class can access it from there.
With this, SSL Peer Verification is taken care of. We just have to create an instance of MyHttpClient in place of DefaultHttpClient and Peer Verification will be handled by itself.
4. Process for Host Verification
Android supports only the host/domain via which the web service is being called - if any other host is tried to connect it throws exception. For example, if our application connects to a host, and then tries to connect another host for any reason, Android won't allow to do that. For this to be allowed, we got to set the hostnames that we want to allow the application to access.
Collapse
public class MyHostVerifier extends org.apache.http.conn.ssl.AbstractVerifier {
String[] allowHost = {"my.ultra.com", "your.ultra.com", "ours.ultra.com"};
@Override
public void verify(String host, String[] cns,
String[] subjectAlts) throws SSLException {
// If the host is any the hosts to be allowed, return, else throw exception
for (int i=0; i < allowHost.length; i++) {
if (host == allowHost[i])
return;
}
throw SSLException;
}
}
Uncomment setHostVerifier in the MyHttpClient class and our class is ready to handle SSL Host Verification as well.
0 件のコメント:
コメントを投稿