Android webview手动校验https证书(通过星空武哥)

  

有些时候由于Android系统的bug或者其他的原因,导致我们的webview不能验证通过我们的https证书,最明显的例子就是华为手机mate7升级到Android7.0后,手机有些网站打不开了,而更新了webview的补丁后就没问题了,充分说明系统的错误对我们混合开发webview加载https地址的影响是巨大的。那么我们怎么去解决这个问题呢?

  

 Android webview手动校验https证书(通过星空武哥)

  

首先我们去分析一下出现的原因
  当webview加载https地址的时候,如果因为证书的问题出错的时候就会走onReceivedSslError()方法

        webView。setWebViewClient(新WebViewClient () {      @Override   公共空间alt=" Android webview手动校验https证书(通过星空武哥)">

  

handler.cancel()就是让加载的页面白屏,所有导致了如果webview校验证书存在异常,android在默认情况下会显示白屏,我们也可调用handler.proceed(),大多时候很多人都是这个处理,但是这也就意味着https证书失去了他存在的意义了。

  

 Android webview手动校验https证书(通过星空武哥)

  

那么如果你的网站证书是正常的,但是因为系统的错误导致了加载异常,这时候就需要我们手动校验了。
  其实我们是可以手动校验网站证书的sha256,如果异常之后校验sha256就执行handler.proceed(),失败就退出应用。
  <强>首先我们要获取网站的证书
  利用谷歌浏览器,打开网址并且按下“F12”,打开开发者模式

  

 Android webview手动校验https证书(通过星空武哥)”> <br/>
  </p>
  <p>一步一步导出证书</p>
  <p> <img src=

  

然后在打开sha256校验网址:http://www.atool.org/file_hash.php

  http://tools.jb51.net/password/sha_encode

  

 Android webview手动校验https证书(通过星空武哥)

  

这样就获取到了证书的sha256的值,写了一个工具类

     /* *   * SSL证书错误,手动校验https证书   *   * @param cert https证书   * @param sha256Str sha256值   * @return真通过,假失败   */公共静态布尔isSSLCertOk (SslCertificate cert字符串sha256Str) {   byte [] SSLSHA256=hexToBytes (sha256Str);   捆包=SslCertificate.saveState (cert);   如果(包!=null) {   byte[]字节=bundle.getByteArray (“x509证书”);   如果(字节!=null) {   尝试{   CertificateFactory cf=CertificateFactory.getInstance (“x”);   证书ca=cf.generateCertificate(新ByteArrayInputStream(字节));   MessageDigest sha256=MessageDigest.getInstance (sha - 256);   byte[]键=sha256.digest (((X509Certificate) ca) .getEncoded ());   返回数组。=(关键,SSLSHA256);   }捕捉(异常e) {   e.printStackTrace ();   }   }   }   返回错误;   }/* *   * hexString转byteArr   * & lt; p>,例如:& lt;/p>   * hexString2Bytes (00 a8)返回{0,(字节)0 xa8}   *   * @param hexString   * @return字节数组   */公共静态byte [] hexToBytes(字符串hexString) {      如果(hexString==null | | hexString.trim () . length ()==0)   返回null;      int长度=hexString.length ()/2;   char [] hexChars=hexString.toCharArray ();   byte[]字节=新字节(长度);   字符串hexDigits=?123456789六边形abcdef”;   for (int i=0;我& lt;长度;我+ +){   int pos=我* 2;//两个字符对应一个字节   int h=hexDigits.indexOf (hexChars (pos)) & lt; & lt;4;//注1   int l=hexDigits。indexOf (hexChars [pos + 1]);//注2   如果(h==1 | | l==1){//非16进制字符   返回null;   }   字节[我]=(字节)(h | l);   }   返回字节;   }   之前      

然后在onReceivedSslError()判断

        webView。setWebViewClient(新WebViewClient () {   @Override   公共空间>/* *   *证书还没有有效的   */公共静态最终int SSL_NOTYETVALID=0;/* *   *证书已经过期   */公共静态最终int SSL_EXPIRED=1;/* *   *的主机名不匹配   */公共静态最终int SSL_IDMISMATCH=2;/* *   *不受信任的证书颁发机构   */公共静态最终int SSL_UNTRUSTED=3;/* *   *证书的日期是无效的   */公共静态最终int SSL_DATE_INVALID=4;/* *   *一个通用的错误发生   */公共静态最终int SSL_INVALID=5;

Android webview手动校验https证书(通过星空武哥)