版权声明:本博客主要记录学习笔记和遇到的一些问题解决方案,转载请注明出处! https://blog.csdn.net/u010982507/article/details/86165390
使用OkHttp或者HttpUrlConnection验证证书和域名的实现已经在 https://mp.csdn.net/mdeditor/85266096 中讲解了,那么有的App中使用了webview加载html,在html中使用ajax请求Https服务,又如何进行证书的安全校验呢?
本文主要讲解webview实现Https自制证书的校验。
我们使用Android的webview的时候会设置一个WebViewClient
,而如果请求Https发生错误的时候,就会调用WebViewClient
的onReceivedSslError
方法,如下所示:
WebView webView = new WebView(getContext());
webView.setWebViewClient(new WebViewClient(){
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
super.onReceivedSslError(view, handler, error);
}
});
super.onReceivedSslError(view, handler, error);
默认继承父类的实现,父类的实现是handler.cancel();
取消通信。所以我们要做的就是在onReceivedSslError
方法中进行证书校验。
onReceivedSslError
方法参数分析
WebView view
参数
这个没什么可说的,就是当前的webview对象。SslErrorHandler handler
参数
点进源码可以看到,就一个构造方法和两个类方法。proceed()
方法是允许所有网络访问,cancel()
方法是取消所有网络访问。
public class SslErrorHandler extends Handler {
/**
* @hide Only for use by WebViewProvider implementations.
*/
@SystemApi
public SslErrorHandler() {}
/**
* Proceed with the SSL certificate.
*/
public void proceed() {}
/**
* Cancel this request and all pending requests for the WebView that had
* the error.
*/
public void cancel() {}
}
SslError error
参数
点进SslError
源码可以看到这个类的属性和方法
主要属性有:
SSL_NOTYETVALID
:证书不合法
SSL_EXPIRED
:证书超出有效期
SSL_IDMISMATCH
:域名不匹配
SSL_UNTRUSTED
:不受信的证书
SSL_DATE_INVALID
:证书日期无效
SSL_INVALID
:一般性错误
除了几个构造方法外,主要方法有:
getUrl()
:获取当前请求的url
getPrimaryError()
:获取错误类型
getCertificate()
:获取当前证书
证书的sha256值校验
判断逻辑是:
1、获取当前webview的证书的sha256值
2、获取客户端证书的sha256值
3、对比两个证书的sha256值,如果相等,则调用handler.proceed()
方法,如果不相等,则调用弹出提示框,并退出应用程序。
WebView webView = new WebView(getContext());
webView.setWebViewClient(new WebViewClient(){
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
String certSha256 = SSLSocketCert.getSSLCertSHA256FromCert(view.getContext().getAssets().open("client.crt"));
String serverSha256 = SSLSocketCert.getSSLCertFromServer(error.getCertificate());
if (certSha256.equalsIgnoreCase(serverSha256)) {
handler.proceed();
} else {
DialogUtil.showSingleDialog(view.getContext(), "警告", "证书校验失败", false, "退出", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
System.exit(0);
}
});
}
}
});
上面代码用到了SSLSocketCert
和DialogUtil
工具类,DialogUtil
可以使用自己的,SSLSocketCert
已上传到
https://download.csdn.net/download/u010982507/10907473