首先是服务端的https环境搭建:
我使用的是tomcat容器,在windows环境下部署的:
(试过Mac环境,但是Mac的java密钥库的默认密码好像是changeme,windows下默认是changeit,在Mac下启动tomcat的时候会碰到密码验证错误 java.security.UnrecoverableKeyException: Password verification failed
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:770)
如果使用Mac系统部署服务端环境的同学希望)接下来需要利用java的keytool生成https所需要的密钥库和证书:
服务端的搭建可以参考:https服务端环境搭建
服务端搭建需要注意的一个问题:
生成密钥库文件(即链接中的server.ks文件)配置的CN=localhost是需要配置你的android客户端访问的主机名(ip地址或者是域名) 这里面配置的参数(即localhost)在android客户端会进行主机名验证,如果不是你android访问的主机名,客户端会过不了HostNameVerifier的验证。
搭建成功之后可通过Chrome浏览器访问搭建好的服务端,保存服务端下发的证书。
接下来是客户端:
将保存下来的证书拷贝到android客户端的assert文件夹下:
InputStream ins = null;
String result = "";
try {
//下载的证书放到项目中的assets目录中
ins = getAssets().open("my.cer");
CertificateFactory cerFactory = CertificateFactory
.getInstance("X.509");
Certificate cer = cerFactory.generateCertificate(ins);
KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
keyStore.load(null,null);
//将客户端保存的证书存放至密钥库并添加为信任证书
keyStore.setCertificateEntry("trust", cer);
SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore);
Scheme sch = new Scheme("https", socketFactory, 8443);
HttpClient mHttpClient = new DefaultHttpClient();
mHttpClient.getConnectionManager().getSchemeRegistry()
.register(sch);
BufferedReader reader = null;
try {
// Log.d(TAG, "executeGet is in,murl:" + mUrl);
HttpGet request = new HttpGet();
request.setURI(new URI(mUrl));
HttpResponse response = mHttpClient.execute(request);
if (response.getStatusLine().getStatusCode() != 200) {
request.abort();
return result;
}
reader = new BufferedReader(new InputStreamReader(response
.getEntity().getContent()));
StringBuffer buffer = new StringBuffer();
String line = null;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
result = buffer.toString();
// Log.d(TAG, "mUrl=" + mUrl + "\nresult = " + result);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
}
}
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
} finally {
try {
if (ins != null)
ins.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(result);
在android2.3版本以后,网络请求不能在UI主线程执行,所以需要进行判断
String strVer=android.os.Build.VERSION.RELEASE;
strVer=strVer.substring(0,3).trim();
float fv=Float.valueOf(strVer);
if(fv>2.3)
{
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // 这里可以替换为detectAll() 就包括了磁盘读写和网络I/O
.penaltyLog() //打印logcat,当然也可以定位到dropbox,通过文件保存相应的log
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects() //探测SQLite数据库操作
.penaltyLog() //打印logcat
.penaltyDeath()
.build());
}