您的位置:首页 > 理论基础 > 计算机网络

android 让webview支持https 双向认证(SSL)

2013-07-03 15:15 681 查看

前言:

最近完成一个项目,安全级别比较高。所以涉及到https双向认证,在网上找了很多资料都没有完美的解决方案。最后参考了org.sandrob.sslexample的实现方式,结合实际情况才完成该技术难题,现在分享一下我的实现方案来弥补这方面的空白。

正文:

1.android 4.0(不包含)以下版本的实现方法:

1.1 书写认证

private SSLContext createSSLContext() {
SSLContext localSSLContext = null;
try {
// 创建一个证书库,并将证书导入证书库
KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
keyStore.load(
mContext.getResources().openRawResource(R.raw.client),//client 是*.pfx文件
CERTFILE_PASSWORD.toCharArray());//CERTFILE_PASSWORD 为你的证书的密码
KeyManagerFactory localKeyManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
localKeyManagerFactory.init(keyStore,
CERTFILE_PASSWORD.toCharArray());
KeyManager[] arrayOfKeyManager = localKeyManagerFactory
.getKeyManagers();
localSSLContext = SSLContext.getInstance("TLS");
localSSLContext.init(arrayOfKeyManager, trustAllCerts,
new SecureRandom());
} catch (Exception ex) {
ex.printStackTrace();
}
return localSSLContext;
}


/**
* 设置webview的ssl双向认证
* 注意:改方法只支持android4.0(不包含)一下
* 该方法调用一次即可
* <P>Author : mingli </P>
* <P>Date : 2013-7-2 </P>
*/
public boolean setWebViewSSLCert() {
boolean issuc = false;// true 代表验证和设置成功
if (Build.VERSION.SDK_INT >= 14){
return issuc;
}

try {
Field[] arrayOfField = Class.forName(
"android.net.http.HttpsConnection").getDeclaredFields();
for (Field localField : arrayOfField) {
if (localField.getName().equals("mSslSocketFactory")) {//采用反射的方式修改mSslSocketFactory变量
localField.setAccessible(true);
localField.set(null,createSSLContext().getSocketFactory());
issuc = true;
break;
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return issuc;
}


1.2 调用

在webview初始化或者application 等,需要用https认证的地方调用 setWebViewSSLCert方法即可。

2.android 4.0(包含)以上版本的实现方法:

2.1 书写认证

private X509Certificate[] mX509Certificates;
private PrivateKey mPrivateKey;
private void initPrivateKeyAndX509Certificate()
throws Exception {
KeyStore keyStore;
// 创建一个证书库,并将证书导入证书库
KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
keyStore.load(
mContext.getResources().openRawResource(R.raw.client),
CERTFILE_PASSWORD.toCharArray());
Enumeration<?> localEnumeration;
localEnumeration = keyStore.aliases();
while (localEnumeration.hasMoreElements()) {
String str3 = (String) localEnumeration.nextElement();
mPrivateKey = (PrivateKey) keyStore.getKey(str3,
CERTFILE_PASSWORD.toCharArray());
if (mPrivateKey == null) {
continue;
} else {
Certificate[] arrayOfCertificate = keyStore
.getCertificateChain(str3);
mX509Certificates = new X509Certificate[arrayOfCertificate.length];
for (int j = 0; j < mX509Certificates.length; j++) {
mX509Certificates[j] = ((X509Certificate) arrayOfCertificate[j]);
}
}
}
}

public class BasicWebViewClientEx extends WebViewClient {

private X509Certificate[] certificatesChain;
private PrivateKey clientCertPrivateKey;

public BasicWebViewClientEx(AbstractActivity activity) {
mActivity = activity;
certificatesChain = getX509Certificates();//此处就是上文中的mX509Certificates
clientCertPrivateKey = getPrivateKey();//次处就是上文中的mPrivateKey
}

public void onReceivedClientCertRequest(WebView view,
ClientCertRequestHandler handler, String host_and_port) {
//注意该方法是调用的隐藏函数接口。这儿是整个验证的技术难点:就是如何调用隐藏类的接口。
//方法:去下载一个android4.2版本全编译后的class.jar 然后导入到工程中
if((null != clientCertPrivateKey) && ((null!=certificatesChain) && (certificatesChain.length !=0))){
handler.proceed(this.clientCertPrivateKey, this.certificatesChain);
}else{
handler.cancel();
}
}

@Override
public void onReceivedSslError(final WebView view, SslErrorHandler handler,
SslError error) {
handler.proceed();
}

}



2.2 调用


mWebView.setWebViewClient(new BasicWebViewClientEx());

2.3 编译

方案一:到android 4.2 源码环境下编译

方案二:(推荐)

1.去下载一个全编译的class.jar(http://download.csdn.net/detail/sfhong2008/5506219)

2.把该class.jar导入工程。步骤如下:(http://www.linuxidc.com/Linux/2012-02/54978.htm)

使用Eclipse,Android工程添加library(BuildPath -> Add Libraries->User Library->New User Library),将.jar文件加入添加到library,同时勾选“SystemLibrary”选项,www.linuxidc.com 以避免产生“java.lang.OutOfMemoryError:Java Heap Space”错误。如果已经正确导入了jar库,却仍然找不到隐藏的API。原因可能是Buildclass path order不正确,即android.jar和classes.jar的导入顺序不对,具体调节Buildclass
path order,选择Build Path-> Config Build Path->Order and Export,调整自定义的library与android.jar的顺序。

3.编译

后记:

分享完毕,欢迎大家拍砖和提问哦。共同进步……
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: