WebView加载自签名认证的https网址
加载https网址安全性提高很多,但是官方认证签名是需要钱的。所以自签名认证就出来了,WebView要添加证书认证后也是能显示的
双向认证签名
必须证书:cer,p12
存放路径:main下面的assets文件夹下,没有的自己新建
1.重写WebViewClient
public class SslPinningWebViewClient extends WebViewClient {
//private LoadedListener listener;
private SSLContext sslContext;
private int url_type;
public SslPinningWebViewClient() throws IOException {
//this.listener = listener;
// 添加cer证书
List certificates = new ArrayList<>();
List certs_data = NetConfig.getCertificatesData();
// 将字节数组转为数组输入流
if (certs_data != null && !certs_data.isEmpty()) {
for (byte[] bytes : certs_data) {
certificates.add(new ByteArrayInputStream(bytes));
}
}
prepareSslPinning(certificates);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
LogUtils.i("url_type", url_type + "a");
view.loadUrl(url);
if (url_type == 2) {
return false;
}
return true;
}
public SslPinningWebViewClient(int url_type) throws IOException {
//this.listener = listener;
this.url_type = url_type;
// 添加cer证书
List certificates = new ArrayList<>();
List certs_data = NetConfig.getCertificatesData();
// 将字节数组转为数组输入流
if (certs_data != null && !certs_data.isEmpty()) {
for (byte[] bytes : certs_data) {
certificates.add(new ByteArrayInputStream(bytes));
}
}
prepareSslPinning(certificates);
}
@Override
public WebResourceResponse shouldInterceptRequest(final WebView view, String url) {
LogUtils.i("shouldInterceptRequest", "shouldInterceptRequest1");
return processRequest(url);
}
private WebResourceResponse processRequest(String webUrl) {
LogUtils.i("SSL_PINNING_WEBVIEWS", "GET: " + webUrl.toString());
try {
// Setup connection
URL url = new URL(webUrl);
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
// Set SSL Socket Factory for this request
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
//很重要,验证证书
urlConnection.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
// Get content, contentType and encoding
InputStream is = urlConnection.getInputStream();
String contentType = urlConnection.getContentType();
String encoding = urlConnection.getContentEncoding();
// If got a contentType header
if (contentType != null) {
String mimeType = contentType;
// Parse mime type from contenttype string
if (contentType.contains(";")) {
mimeType = contentType.split(";")[0].trim();
}
LogUtils.i("SSL_PINNING_WEBVIEWS", "Mime: " + mimeType);
//listener.Loaded(webUrl.toString());
// Return the response
return new WebResourceResponse(mimeType, encoding, is);
}
} catch (Exception e) {
e.printStackTrace();
if (isCause(CertPathValidatorException.class, e)) {
//listener.PinningPreventedLoading(webUrl);
}
LogUtils.i("SSL_PINNING_WEBVIEWS", e.getLocalizedMessage());
}
// Return empty response for this request
return new WebResourceResponse(null, null, null);
}
private void prepareSslPinning(List certificates) throws IOException {
try {
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance("X509");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
KeyStore keyStore = KeyStore.getInstance("PKCS12");
KeyStore keyStore2 = KeyStore.getInstance(KeyStore.getDefaultType());
//读取证书
InputStream ksIn = getResources().getAssets().open("mykey.p12");
//加载证书
keyStore2.load(null);
keyStore.load(ksIn, "yibanyiban".toCharArray());
ksIn.close();
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
try {
for (int i = 0, size = certificates.size(); i < size; ) {
InputStream certificate = certificates.get(i);
String certificateAlias = Integer.toString(i++);
keyStore2.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
if (certificate != null)
certificate.close();
}
} catch (IOException e) {
e.printStackTrace();
}
sslContext = SSLContext.getInstance("TLS");
keyManagerFactory.init(keyStore, "yibanyiban".toCharArray());
trustManagerFactory.init(keyStore2);
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
} catch (Exception e) {
e.printStackTrace();
}
}
private static 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 static KeyManager[] prepareKeyManager(InputStream bksFile, String password) {
try {
if (bksFile == null || password == null) return null;
KeyStore clientKeyStore = KeyStore.getInstance("PKCS12");
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;
}
private 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 boolean isCause(
Class extends Throwable> expected,
Throwable exc
) {
return expected.isInstance(exc) || (
exc != null && isCause(expected, exc.getCause())
);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
} }
注:上面很重要部分真的很重要
2.NetConfig读取cer证书
public class NetConfig {
// 证书数据
private static List CERTIFICATES_DATA = new ArrayList<>();
/**
* 添加https证书
* @param inputStream
*/
public synchronized static void addCertificate(InputStream inputStream) {
if (inputStream != null) {
try {
int ava = 0;// 数据当次可读长度
int len = 0;// 数据总长度
ArrayList data = new ArrayList<>();
while ((ava = inputStream.available()) > 0) {
byte[] buffer = new byte[ava];
inputStream.read(buffer);
data.add(buffer);
len += ava;
}
byte[] buff = new byte[len];
int dstPos = 0;
for (byte[] bytes:data) {
int length = bytes.length;
System.arraycopy(bytes, 0, buff, dstPos, length);
dstPos += length;
}
CERTIFICATES_DATA.add(buff);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* https证书
* @return
*/
public static List getCertificatesData() {
return CERTIFICATES_DATA;
}}
3.MyApplication读cer###
/**
* 读取cer证书
*/
private void readCer() {
// 添加https证书
try {
InputStream is = getAssets().open("tomcat.cer");
NetConfig.addCertificate(is); // 这里将证书读取出来,,放在配置中byte[]里
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
写这个方法后,在OnCreate()中调用
4.webview的使用
SslPinningWebViewClient webViewClient = null;
try {
webViewClient = new SslPinningWebViewClient();
} catch (IOException e) {
e.printStackTrace();
}
//采用自定义WebViewClient
wvMain.setWebViewClient(webViewClient);
在做之前可以先在电脑浏览器上试证书是否是能用的,至于方法百度。如果证书能用,基本通过上面步骤是没问题的。
这篇文章在csdn上面也有。
但都是我的,哈哈
还有问题可私信我