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 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上面也有。
但都是我的,哈哈
还有问题可私信我