最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android webview手動(dòng)校驗(yàn)https證書(by 星空武哥)

 更新時(shí)間:2017年09月03日 13:24:49   投稿:mdxy-dxy  
有些時(shí)候由于Android系統(tǒng)的bug或者其他的原因,導(dǎo)致我們的webview不能驗(yàn)證通過我們的https證書,最明顯的例子就是華為手機(jī)mate7升級(jí)到Android7.0后,手機(jī)有些網(wǎng)站打不開了,而更新了webview的補(bǔ)丁后就沒問題了

有些時(shí)候由于Android系統(tǒng)的bug或者其他的原因,導(dǎo)致我們的webview不能驗(yàn)證通過我們的https證書,最明顯的例子就是華為手機(jī)mate7升級(jí)到Android7.0后,手機(jī)有些網(wǎng)站打不開了,而更新了webview的補(bǔ)丁后就沒問題了,充分說(shuō)明系統(tǒng)的bug對(duì)我們混合開發(fā)webview加載https地址的影響是巨大的。那么我們?cè)趺慈ソ鉀Q這個(gè)問題呢?

首先我們?nèi)シ治鲆幌鲁霈F(xiàn)的原因
當(dāng)webview加載https地址的時(shí)候,如果因?yàn)樽C書的問題出錯(cuò)的時(shí)候就會(huì)走onReceivedSslError()方法

webView.setWebViewClient(new WebViewClient() { 
 
  @Override 
  public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { 
    super.onReceivedSslError(view, handler, error); 
  } 
} 

而super.onReceivedSslError()默認(rèn)是

handler.cancel() 就是讓加載的頁(yè)面白屏,所有導(dǎo)致了如果webview校驗(yàn)證書存在異常,android在默認(rèn)情況下會(huì)顯示白屏,我們也可調(diào)用handler.proceed(),大多時(shí)候很多人都是這個(gè)處理,但是這也就意味著https證書失去了他存在的意義了。

那么如果你的網(wǎng)站證書是正常的,但是因?yàn)橄到y(tǒng)的bug導(dǎo)致了加載異常,這時(shí)候就需要我們手動(dòng)校驗(yàn)了。
其實(shí)我們是可以手動(dòng)校驗(yàn)網(wǎng)站證書的sha256,如果異常之后校驗(yàn)sha256就執(zhí)行handler.proceed(),失敗就退出應(yīng)用。
首先我們要獲取網(wǎng)站的證書
利用谷歌瀏覽器,打開網(wǎng)址并且按下“F12”,打開開發(fā)者模式


一步一步導(dǎo)出證書

然后在打開sha256校驗(yàn)網(wǎng)址:http://www.atool.org/file_hash.php

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

這樣就獲取到了證書的sha256的值,寫了一個(gè)工具類

  /**
   * SSL證書錯(cuò)誤,手動(dòng)校驗(yàn)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轉(zhuǎn)byteArr
   * <p>例如:</p>
   * hexString2Bytes("00A8") returns { 0, (byte) 0xA8 }
   *
   * @param hexString
   * @return 字節(jié)數(shù)組
   */
  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; // 兩個(gè)字符對(duì)應(yīng)一個(gè)byte
      int h = hexDigits.indexOf(hexChars[pos]) << 4; // 注1
      int l = hexDigits.indexOf(hexChars[pos + 1]); // 注2
      if (h == -1 || l == -1) { // 非16進(jìn)制字符
        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) {
			// 如果手動(dòng)校驗(yàn)sha256成功就允許加載頁(yè)面
			if (SSLCertUtil.isSSLCertOk(error.getCertificate(), "6683c9584b8287ec3a50e312f4a540c79938aaeb76bd02e40a9ca037ee5d24f4")) {
				handler.proceed();
			} else {
				try {
					new AlertDialog.Builder(MainActivity.this)
							.setTitle("警告")
							.setMessage("證書校驗(yàn)失敗")
							.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();
		}
	}
});

這里我們只是真對(duì)SslError.SSL_INVALID進(jìn)行了判斷,可能還有其他情況,根據(jù)自己的情況判定。

/**
 * 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;

這樣就完成了手動(dòng)校驗(yàn)https證書校

相關(guān)文章

  • Android中的Bitmap緩存池使用詳解

    Android中的Bitmap緩存池使用詳解

    這篇文章主要介紹了Android中的Bitmap緩存池使用詳解,本文主要目的是講解如何使用緩存來(lái)提高UI的載入輸入和滑動(dòng)的流暢性,需要的朋友可以參考下
    2015-01-01
  • RecyclerView中使用CheckBox出現(xiàn)勾選混亂的解決方法

    RecyclerView中使用CheckBox出現(xiàn)勾選混亂的解決方法

    這篇文章主要為大家詳細(xì)介紹了RecyclerView中使用CheckBox出現(xiàn)勾選混亂的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Android WebView攔截iframe標(biāo)簽內(nèi)部跳轉(zhuǎn)教程

    Android WebView攔截iframe標(biāo)簽內(nèi)部跳轉(zhuǎn)教程

    這篇文章主要介紹了Android WebView攔截iframe標(biāo)簽內(nèi)部跳轉(zhuǎn)教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2020-03-03
  • Android自定義TipView仿QQ長(zhǎng)按后的提示窗口

    Android自定義TipView仿QQ長(zhǎng)按后的提示窗口

    這篇文章主要介紹了Android自定義TipView仿QQ長(zhǎng)按后的提示窗口,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2018-05-05
  • Android setTag方法的key問題解決辦法

    Android setTag方法的key問題解決辦法

    這篇文章主要介紹了Android setTag方法的key問題解決辦法的相關(guān)資料,需要的朋友可以參考下
    2016-09-09
  • 最新評(píng)論

    台湾省| 浦城县| 孟村| 沽源县| 德州市| 永和县| 溧阳市| 武平县| 辽中县| 双桥区| 开封县| 溆浦县| 大庆市| 安西县| 扎囊县| 准格尔旗| 瑞昌市| 桐梓县| 嘉禾县| 文化| 呼伦贝尔市| 云南省| 雷州市| 莱阳市| 卢龙县| 大安市| 若尔盖县| 聂拉木县| 弥渡县| 高密市| 莲花县| 修武县| 洛浦县| 扬州市| 平凉市| 丰镇市| 廊坊市| 湖口县| 平湖市| 固镇县| 邛崃市|