问题的开始:
随着android API的节节高升,高API的android手机市场占比也日趋变大,之前sdk中开发的web容器在加载公司的schema为https的h5页面时,白屏了无法正常加载!
问题的定位:
找了很久【在重载Webview对应的接口回调方法时没有写全,log日志不全】,最后一个个失败回调方法添加完成后发现是
出在了 onReceiverdSslError方法回调中,这里将super改为proceed即可正常打开页面收工!但介么做是有问题滴!因为这么做
https的意义就没啥了(这不是我说的,这是公司的安全部分跑包后说的...)proceed这个api相当于对出现问题的页面都放权加载了,如果加载了别人注入的页面那么就会造成风险。这里采取的解决方案是:
校验对应https的证书!
问题的解决:
1.获取证书【请自行参考网上的获取对应要加载的https地址的证书 我这里用windows exploer浏览器做的操作】
2.证书信息的提取
如何解决该问题重点在如何校验https证书,这里要明白证书本质的含义只不过是一个用特殊后缀命名的二进制文件而已,只是这个二进制文件中存有匹配验证的数据!
3. 第二步转换的对应数据信息如何转换成代码中能够使用的资源呢?
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
if (error.getPrimaryError() == SslError.SSL_DATE_INVALID // 日期不正确
|| error.getPrimaryError() == SslError.SSL_EXPIRED // 日期不正确
|| error.getPrimaryError() == SslError.SSL_INVALID // webview BUG
|| error.getPrimaryError() == SslError.SSL_UNTRUSTED) { // 根证书丢失
if (SSLChecker.chkMySSLCNCert(error.getCertificate())) {
handler.proceed(); // 如果证书一致,忽略错误
}
}
handler.cancel();
通过上述代码片段中的 chkMySSLCNCert方法:
public static boolean chkMySSLCNCert(SslCertificate cert) {
byte[] MySSLCNSHA256_xxx_COM_CN = { 36,7,-45,13,31,42,-123,126,81,68,-117,-69,-28,-126,-115,104,-22,-105,101,-73,5,-78,80,112,-65,11,-21,13,-74,4,19,65 }; //证书指纹
Bundle bundle = SslCertificate.saveState(cert);
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, MySSLCNSHA256_xxx_COM_CN);
} catch (Exception Ex) {}
}
return false;
}
代码中的byte 数组对应之前sha256 的hex String,将hex String转换成byte[]即可完成webview 对https证书的校验过程!
另可参考:
https://blog.csdn.net/lsyz0021/article/details/54669914
https://blog.csdn.net/sd19871122/article/details/54632199