使用:
my_webview.setWebViewClient(new SslWebViewClient(this));
直接复制下面2个类之后webview调用(虽然代码有点多,但其实有很多是没有用到的!只是因为不同证书类型可能会用到不同的代码而暂时保留)
import android.util.Log;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* Created by tyl
* 2018/7/12/012
* Describe:
*/
public class TrustAllCerts implements X509TrustManager {
// 默认的下面3个接口都会抛出一个异常,这里直接去掉异常,就是客户端忽略验证服务器端的验证信息直接通过
@Override
public void checkClientTrusted(
X509Certificate[] chain, String authType) {
Log.e("tyl","checkClientTrusted");
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
Log.e("tyl","checkServerTrusted");
}
@Override
public X509Certificate[] getAcceptedIssuers() {
Log.e("tyl","getAcceptedIssuers");
return new X509Certificate[]{};}
}
package com.tgdz.my.testhttps;
import android.annotation.TargetApi;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class SslWebViewClient extends WebViewClient {
private SSLContext sslContext;
private static final String KEY_STORE_TYPE_BKS = "bks";//证书类型
private static final String KEY_STORE_TYPE_P12 = "PKCS12";//证书类型
private static final String KEY_STORE_PASSWORD = "";//证书密码(应该是客户端证书密码)
private static final String KEY_STORE_TRUST_PASSWORD = "123456";//授信证书密码(应该是服务端证书密码)
private static InputStream trust_input;
private static InputStream client_input;
public SslWebViewClient(Context context) {
try {
//服务器授信证书
// trust_input = context.getResources().getAssets().open("client.bks");
//客户端证书
client_input = context.getResources().getAssets().open("ca.p12");
sslContext = SSLContext.getInstance("TLS");
// KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
// trustStore.load(trust_input, KEY_STORE_TRUST_PASSWORD.toCharArray());
KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE_P12);
keyStore.load(client_input, KEY_STORE_PASSWORD.toCharArray());
// TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
// trustManagerFactory.init(trustStore);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, KEY_STORE_PASSWORD.toCharArray());
sslContext.init(keyManagerFactory.getKeyManagers(),new TrustManager[]{new TrustAllCerts()}, new SecureRandom());
// SSLSocketFactory factory = sslContext.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
Log.e("tyl","Exception="+e.getMessage());
} finally {
try {
// trust_input.close();
client_input.close();
} catch (IOException e) {
e.printStackTrace();
Log.e("tyl","Exception="+e.getMessage());
}
}
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
return processRequest(Uri.parse(url));
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
return processRequest(request.getUrl());
}
private WebResourceResponse processRequest(Uri uri) {
try {
//设置连接
URL url = new URL(uri.toString());
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
//为request设置SSL Socket Factory
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
urlConnection.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
//获取请求的内容、contentType、encoding
InputStream inputStream = urlConnection.getInputStream();
String contentType = urlConnection.getContentType();
String encoding = urlConnection.getContentEncoding();
if (null != contentType){
String mimeType = contentType;
if (contentType.contains(";")){
mimeType = contentType.split(";")[0].trim();
}
//返回新的response
return new WebResourceResponse(mimeType, encoding, inputStream);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private TrustManager[] prepareTrustManager(InputStream... certificates) {
if (certificates == null || certificates.length <= 0){
return null;
}
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
int index = 0;
for (InputStream certificate : certificates) {
String certificateAlias = Integer.toString(index++);
keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
try {
if (certificate != null)
certificate.close();
} catch (IOException e){
}
}
TrustManagerFactory trustManagerFactory = null;
trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
return trustManagers;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private KeyManager[] prepareKeyManager(InputStream bksFile, String password) {
try {
if (bksFile == null || password == null){
return null;
}
KeyStore clientKeyStore = KeyStore.getInstance("BKS");
clientKeyStore.load(bksFile, password.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(clientKeyStore, password.toCharArray());
return keyManagerFactory.getKeyManagers();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) {
for (TrustManager trustManager : trustManagers) {
if (trustManager instanceof X509TrustManager) {
return (X509TrustManager) trustManager;
}
}
return null;
}
public static class MyTrustManager implements X509TrustManager{
private X509TrustManager defaultTrustManager;
private X509TrustManager localTrustManager;
public MyTrustManager(X509TrustManager localTrustManager) throws NoSuchAlgorithmException, KeyStoreException {
TrustManagerFactory var4 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
var4.init((KeyStore) null);
defaultTrustManager = chooseTrustManager(var4.getTrustManagers());
this.localTrustManager = localTrustManager;
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
try {
defaultTrustManager.checkServerTrusted(chain, authType);
} catch (CertificateException ce) {
localTrustManager.checkServerTrusted(chain, authType);
}
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
public static class UnSafeTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
}
各类知识点整理:
- android https双向验证 前言及总结:https://www.jianshu.com/p/07ce321d80ab
- 单双向验证基础知识点: https://www.jianshu.com/p/ea5f4b1d9c00
- phpstudy搭建本地服务器: https://www.jianshu.com/p/bbf853fc28f3
- 浏览器获取证书文件(p12转cer):https://www.jianshu.com/p/7f74acab6c74
- https双向认证证书生成:https://www.jianshu.com/p/094c7fc8cb85
- android okhttps双向验证(代码实现):https://www.jianshu.com/p/6229d10d3550
- 配置完成后的测试:https://www.jianshu.com/p/cfcf708a591a
- Glide okhttps证书验证全局配置:https://www.jianshu.com/p/ac0b5c5f3ca7
工具类:
- P12证书转BKS证书:https://www.jianshu.com/p/2a96c36b27fe
- 服务器网址检测(兼容性及协议检测):https://www.ssllabs.com/index.html
源码:
- github:https://github.com/fs437563/android_https