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

Android webview手动校验https证书(by 星空武哥),第1张

概述有些时候由于Android系统的bug或者其他的原因,导致我们的webview不能验证通过我们的https证书,最明显的例子就是华为手机mate7升级到Android7.0后,手机有些网站打不开了,而更新了webview的补丁后就没问题了,充分

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

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

webVIEw.setWebVIEwClIEnt(new WebVIEwClIEnt() {    @OverrIDe   public 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

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

这样就获取到了证书的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() {	@OverrIDe	public voID onReceivedSslError(WebVIEw vIEw,SslError error) {		super.onReceivedSslError(vIEw,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() {								@OverrIDe								public 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 webview手动校验https证书(by 星空武哥)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1144574.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存