全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

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

有些时候由于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./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, 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() {
								@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证书校


# webview手动校验https证书  # Android okhttp3.0忽略https证书的方法  # Android Https证书过期的两种解决方案  # 加载  # 自己的  # 都是  # 华为  # 就会  # 很多人  # 其他的  # 也可  # 这也  # 就没  # 写了  # 升级到  # 按下  # 打不开  # 解决这个问题  # 进行了  # 失去了  # 情况下  # 这时候  # 完成了 


相关文章: 建站之星如何通过成品分离优化网站效率?  如何在VPS电脑上快速搭建网站?  如何用PHP工具快速搭建高效网站?  如何在宝塔面板中创建新站点?  早安海报制作网站推荐大全,企业早安海报怎么每天更换?  Swift中switch语句区间和元组模式匹配  Java解压缩zip - 解压缩多个文件或文件夹实例  网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?  ,南京靠谱的征婚网站?  广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?  C++中引用和指针有什么区别?(代码说明)  如何快速配置高效服务器建站软件?  高防服务器租用指南:配置选择与快速部署攻略  微信小程序 input输入框控件详解及实例(多种示例)  建站之星如何助力网站排名飙升?揭秘高效技巧  自助网站制作软件,个人如何自助建网站?  如何在阿里云高效完成企业建站全流程?  电商网站制作价格怎么算,网上拍卖流程以及规则?  如何通过远程VPS快速搭建个人网站?  网站制作软件免费下载安装,有哪些免费下载的软件网站?  浙江网站制作公司有哪些,浙江栢塑信息技术有限公司定制网站做的怎么样?  如何生成腾讯云建站专用兑换码?  在线流程图制作网站手机版,谁能推荐几个好的CG原画资源网站么?  阿里云网站搭建费用解析:服务器价格与建站成本优化指南  已有域名和空间如何快速搭建网站?  宝塔建站助手安装配置与建站模板使用全流程解析  中山网站推广排名,中山信息港登录入口?  江苏网站制作公司有哪些,江苏书法考级官方网站?  如何选择可靠的免备案建站服务器?  建站10G流量真的够用吗?如何应对访问高峰?  微信小程序制作网站有哪些,微信小程序需要做网站吗?  常州自助建站:操作简便模板丰富,企业个人快速搭建网站  如何在阿里云购买域名并搭建网站?  高防服务器如何保障网站安全无虞?  建站之星logo尺寸如何设置最合适?  如何用VPS主机快速搭建个人网站?  如何在Windows环境下新建FTP站点并设置权限?  行程制作网站有哪些,第三方机票电子行程单怎么开?  建站之星如何配置系统实现高效建站?  广州顶尖建站服务:企业官网建设与SEO优化一体化方案  PHP正则匹配日期和时间(时间戳转换)的实例代码  手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?  如何制作网站标识牌,动态网站如何制作(教程)?  c# 在ASP.NET Core中管理和取消后台任务  建站之星如何一键生成手机站?  教育培训网站制作流程,请问edu教育网站的域名怎么申请?  在线教育网站制作平台,山西立德教育官网?  开源网站制作软件,开源网站什么意思?  网站海报制作教学视频教程,有什么免费的高清可商用图片网站,用于海报设计?  如何在万网开始建站?分步指南解析 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。