Android webview手动校验https证书(by 星空武哥)
来源:互联网 发布:sql数据库编程 编辑:程序博客网 时间:2024/05/22 03:17
转载请标注原创地址:http://blog.csdn.net/lsyz0021/article/details/54669914
有些时候由于Android系统的bug或者其他的原因,导致我们的webview不能验证通过我们的https证书,最明显的例子就是华为手机mate7升级到Android7.0后,手机有些网站打不开了,而更新了webview的补丁后就没问题了,充分说明系统的bug对我们混合开发webview加载https地址的影响是巨大的。那么我们怎么去解决这个问题呢?
首先我们去分析一下出现的原因
当webview加载https地址的时候,如果因为证书的问题出错的时候就会走onReceivedSslError()方法
webView.setWebViewClient(new WebViewClient() {@Overridepublic void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {super.onReceivedSslError(view, handler, error);}}而super.onReceivedSslError()默认是
handler.cancel() 就是让加载的页面白屏,所有导致了如果webview校验证书存在异常,Android在默认情况下会显示白屏,我们也可调用handler.proceed(),大多时候很多人都是这个处理,但是这也就意味着https证书失去了他存在的意义了。
那么如果你的网站证书是正常的,但是因为系统的bug导致了加载异常,这时候就需要我们手动校验了。
其实我们是可以手动校验网站证书的sha256,如果异常之后校验sha256就执行handler.proceed(),失败就退出应用。
首先我们要获取网站的证书
利用谷歌浏览器,打开网址并且按下“F12”,打开开发者模式
一步一步导出证书
然后在打开sha256校验网址:http://www.atool.org/file_hash.php
这样就获取到了证书的sha256的值,写了一个工具类
/** * SSL证书错误,手动校验https证书 * * @param cert https证书 * @param sha256Str sha256值 * @return true通过,false失败 */ public static boolean isSSLCertOk(SslCertificate cert, String sha256Str) { byte[] SSLSHA256 = hexToBytes(sha256Str); Bundle bundle = SslCertificate.saveState(cert); if (bundle != null) { byte[] bytes = bundle.getByteArray("x509-certificate"); if (bytes != null) { try { CertificateFactory cf = CertificateFactory.getInstance("X.509"); Certificate ca = cf.generateCertificate(new ByteArrayInputStream(bytes)); MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); byte[] key = sha256.digest(((X509Certificate) ca).getEncoded()); return Arrays.equals(key, SSLSHA256); } catch (Exception e) { e.printStackTrace(); } } } return false; } /** * hexString转byteArr * <p>例如:</p> * hexString2Bytes("00A8") returns { 0, (byte) 0xA8 } * * @param hexString * @return 字节数组 */ public static byte[] hexToBytes(String hexString) { if (hexString == null || hexString.trim().length() == 0) return null; int length = hexString.length() / 2; char[] hexChars = hexString.toCharArray(); byte[] bytes = new byte[length]; String hexDigits = "0123456789abcdef"; for (int i = 0; i < length; i++) { int pos = i * 2; // 两个字符对应一个byte int h = hexDigits.indexOf(hexChars[pos]) << 4; // 注1 int l = hexDigits.indexOf(hexChars[pos + 1]); // 注2 if (h == -1 || l == -1) { // 非16进制字符 return null; } bytes[i] = (byte) (h | l); } return bytes; }
然后在onReceivedSslError()判断
webView.setWebViewClient(new WebViewClient() {@Overridepublic void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {super.onReceivedSslError(view, handler, error);if (error.getPrimaryError() == SslError.SSL_INVALID) {// 如果手动校验sha256成功就允许加载页面if (SSLCertUtil.isSSLCertOk(error.getCertificate(), "6683c9584b8287ec3a50e312f4a540c79938aaeb76bd02e40a9ca037ee5d24f4")) {handler.proceed();} else {try {new AlertDialog.Builder(MainActivity.this).setTitle("警告").setMessage("证书校验失败").setPositiveButton("退出", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {System.exit(0);dialog.dismiss();}}).show();} catch (Exception e) {e.printStackTrace();}}} else {handler.cancel();}}});
这里我们只是真对SslError.SSL_INVALID进行了判断,可能还有其他情况,根据自己的情况判定。
/** * The certificate is not yet valid */public static final int SSL_NOTYETVALID = 0;/** * The certificate has expired */public static final int SSL_EXPIRED = 1;/** * Hostname mismatch */public static final int SSL_IDMISMATCH = 2;/** * The certificate authority is not trusted */public static final int SSL_UNTRUSTED = 3;/** * The date of the certificate is invalid */public static final int SSL_DATE_INVALID = 4;/** * A generic error occurred */public static final int SSL_INVALID = 5;
这样就完成了手动校验https证书校
出微信 扫码关注下面的微信订阅号,及时获取更多推送文章
- Android webview手动校验https证书(by 星空武哥)
- android studio创建assets目录并且利用webView加载其html(by 星空武哥)
- Android WebView使用详解包括js互调(by 星空武哥)
- Android WebView使用详解包括js互调(by 星空武哥)
- Android webview处理404、500、断网、timeout页面的问题(by 星空武哥)
- Android通知(Notification)详解(by 星空武哥)
- Android 安全--WebView不校验证书漏洞
- Android 4.4系统HTTPS证书校验
- android webview 加载https --忽略证书
- ubuntu下搭建android开发环境(一)安装ubuntu系统(by 星空武哥)
- Jenkins持续化构建Android项目(一)-安装配置Jenkins(by 星空武哥)
- Android的menu(菜单)按钮的使用(by 星空武哥)
- Android手机获取外网ip(by 星空武哥)
- Fiddler抓取Android app网络请求数据包(by 星空武哥)
- Android Studio如何引用so、arr、jar包(by 星空武哥)
- Android UI测试-Espresso环境搭建及测试(by 星空武哥)
- 微信Android热更新Tinker使用详解(by 星空武哥)
- 将Android项目发布到Jcenter(by 星空武哥)
- Elasticsearch 5.x Head插件部署指南
- MYSQL 索引优化全攻略
- 基于LitePal操作数据库的学生管理系统的简单实现
- 微信小程序基础组件之视图容器
- Linux(Centos)之安装Java JDK及注意事项
- Android webview手动校验https证书(by 星空武哥)
- Oracle数据库整库文件路径变更
- android开发之避免使用枚举
- Java Spring Redis搭建
- Springmvc项目启动后定时执行某个方法
- 【C++】n_element的用法
- Linux(Centos)之安装tomcat并且部署Java Web项目
- ROS + Caffe 机器人操作系统框架和深度学习框架笔记 (機器人控制與人工智能)
- jq 命令行 Shell 处理json 格式数据 示例