因为网页中要用到自定义SSL证书,而且密钥是 xxx.p12,
我们是将密钥转化为byte[]的形式传进来的,传入密码,这样来处理SSL
关键在onReceivedClientCertRequest这个方法,要用到隐藏类,因此得用编译android出来的class.jar,不然识别不了该隐藏类
所以自定义WebViewClient如下:
import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.Enumeration; import android.content.Context; import android.net.http.SslError; import android.webkit.ClientCertRequestHandler; import android.webkit.SslErrorHandler; import android.webkit.WebView; import android.webkit.WebViewClient; public class SSLWebViewClient extends WebViewClient{ private X509Certificate[] certificatesChain; private PrivateKey clientCertPrivateKey; byte[] certfile_p12; private String certfile_password = ""; public SSLWebViewClient(Context context, byte[] cert, String pass) throws Exception { super(); certfile_password = pass; certfile_p12 = cert; initPrivateKeyAndX509Certificate(); } private void initPrivateKeyAndX509Certificate() throws Exception { KeyStore keyStore; keyStore = KeyStore.getInstance("PKCS12"); keyStore.load(DataTools.byteTOInputStream(certfile_p12), certfile_password.toCharArray()); Enumeration<?> localEnumeration; localEnumeration = keyStore.aliases(); while (localEnumeration.hasMoreElements()) { String str3 = (String) localEnumeration.nextElement(); clientCertPrivateKey = (PrivateKey) keyStore.getKey(str3, certfile_password.toCharArray()); if (clientCertPrivateKey == null) { continue; } else { Certificate[] arrayOfCertificate = keyStore.getCertificateChain(str3); certificatesChain = new X509Certificate[arrayOfCertificate.length]; for (int j = 0; j < certificatesChain.length; j++) { certificatesChain[j] = ((X509Certificate) arrayOfCertificate[j]); } } } } public void onReceivedClientCertRequest(WebView view, ClientCertRequestHandler handler, String host_and_port) { if((null != clientCertPrivateKey) && ((null!=certificatesChain) && (certificatesChain.length !=0))){ handler.proceed(this.clientCertPrivateKey, this.certificatesChain); }else{ handler.cancel(); } } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } @Override public void onReceivedSslError(final WebView view, SslErrorHandler handler, SslError error) { handler.proceed(); } }
其中用到转换工具类,如下:
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; public class DataTools { final static int BUFFER_SIZE = 4096; /** * 将InputStream转换成String * @param in InputStream * @return String * @throws Exception * */ public static String InputStreamTOString(InputStream in) throws Exception{ ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] data = new byte[BUFFER_SIZE]; int count = -1; while((count = in.read(data,0,BUFFER_SIZE)) != -1) outStream.write(data, 0, count); data = null; return new String(outStream.toByteArray(),"ISO-8859-1"); } /** * 将InputStream转换成某种字符编码的String * @param in * @param encoding * @return * @throws Exception */ public static String InputStreamTOString(InputStream in,String encoding) throws Exception{ ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] data = new byte[BUFFER_SIZE]; int count = -1; while((count = in.read(data,0,BUFFER_SIZE)) != -1) outStream.write(data, 0, count); data = null; return new String(outStream.toByteArray(),"ISO-8859-1"); } /** * 将String转换成InputStream * @param in * @return * @throws Exception */ public static InputStream StringTOInputStream(String in) throws Exception{ ByteArrayInputStream is = new ByteArrayInputStream(in.getBytes("ISO-8859-1")); return is; } /** * 将InputStream转换成byte数组 * @param in InputStream * @return byte[] * @throws IOException */ public static byte[] InputStreamTOByte(InputStream in) throws IOException{ ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] data = new byte[BUFFER_SIZE]; int count = -1; while((count = in.read(data,0,BUFFER_SIZE)) != -1) outStream.write(data, 0, count); data = null; return outStream.toByteArray(); } /** * 将byte数组转换成InputStream * @param in * @return * @throws Exception */ public static InputStream byteTOInputStream(byte[] in) throws Exception{ ByteArrayInputStream is = new ByteArrayInputStream(in); return is; } /** * 将byte数组转换成String * @param in * @return * @throws Exception */ public static String byteTOString(byte[] in) throws Exception{ InputStream is = byteTOInputStream(in); return InputStreamTOString(is); } }
需要用到android便宜出来的class的jar包,已经编译好的放在raw文件夹里,目录结构如下:
编译出来的 sslwebviewclient.jar 就可以在你的项目中使用了。
使用方法如下:
WebView browser = (WebView)findViewById(R.id.id_browser); try { browser.setWebViewClient(new SSLWebViewClient(this, AndroidNaviAPP.getInstance().getPfx(), AndroidNaviAPP.getInstance().getPass())); } catch (Exception e) { //异常处理 }
这样就可以正常打开,自定义密钥的SSL网页了
可能用到的资源文件(包含编译的class.jar 和 我本地生成好的sslwebviewclient.jar,可以直接用,最好自己编):
http://download.csdn.net/detail/zoeice/6485653