1. 程式人生 > >Android中Https通訊實現_ 單向認證

Android中Https通訊實現_ 單向認證

客戶端與服務端單向認證即是在客戶端的網路請求和webview中設定信任所有證書,然後在與服務端進行Https網路通訊的時候,客戶端不必進行證書校驗也能進行網路通訊,否則就會報證書不受信異常。
缺陷:容易受到中間人攻擊。

概覽

  • TrustManager和HostnameVerifier
  • HttpURLConnection信任所有證書
  • OkHttp信任所有證書
  • webview信任所有證書

X509TrustManagerHostnameVerifier

X509TrustManager用於實現SSL證書的安全校驗,若使用不當,將導致APP對SSL證書不作校驗,從而 黑客有了中間人攻擊的可乘之機。開發者常見錯誤:

  • 自定義X509TrustManager,且不做任何校驗邏輯,一般為空實現;

HostnameVerifier用於實現HTTPS通訊中的域名安全校驗,即驗證當前連線的HTTPS站點的SSL證書中的域名是否等於站點本身的域名。開發者常見錯誤:

  • 自定義HostnameVerifier,且不做任何校驗邏輯,一般為return true;
  • 使用Android系統中自帶的不安全的HostnameVerifier,效果等同於不做任何校驗邏輯:
    org.apache.http.conn.ssl.AllowAllHostnameVerifier
    org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public
class SSLSocketClient { //獲取這個SSLSocketFactory public static SSLSocketFactory getSSLSocketFactory() { try { SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, getTrustManager(), new SecureRandom()); return sslContext.getSocketFactory(); } catch (Exception e) { throw new RuntimeException(e); } } //獲取TrustManager private static TrustManager[] getTrustManager() { TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) { } @Override public X509Certificate[] getAcceptedIssuers() { // return null; 或者 return new X509Certificate[]{}; // 空實現 } } }; return trustAllCerts; } //獲取HostnameVerifier public static HostnameVerifier getHostnameVerifier() { HostnameVerifier hostnameVerifier = new HostnameVerifier() { @Override public boolean verify(String s, SSLSession sslSession) { // true表示信任所有域名 return true; } }; return hostnameVerifier; } }

使用Android系統中自帶的不安全的HostnameVerifie

URL url = new URL("https url");
HttpsURLConnection conn= (HttpsURLConnection) url.openConnection();
conn.setHostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

HttpURLConnection信任所有證書

URL url = new URL(fileUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(requestType);
conn.setConnectTimeout(timeOut * 1000);
// 配置https的證書
if ("https".equalsIgnoreCase(url.getProtocol())){
    ((HttpsURLConnection) conn).setSSLSocketFactory(SSLSocketClient.getSSLSocketFactory());
    ((HttpsURLConnection) conn).setHostnameVerifier(SSLSocketClient.getHostnameVerifier());
}

OkHttp信任所有證書

OkHttpClient okHttpClient = new OkHttpClient.Builder()
              .sslSocketFactory(SSLSocketClient.getSSLSocketFactory())
              .hostnameVerifier(SSLSocketClient.getHostnameVerifier())
              .build();

webview信任所有證書

Android系統內建了一些可信機構辦法的證書,可用於作HTTPS證書校驗。實際上,使用Webview元件進HTTPS通訊,其證書驗證環節也是系統預設會去做的。若發現證書不合法,Webview將顯示一個空白頁面,其錯誤在onReceivedSslError()這個方法裡進行處理。
在WebViewClient原始碼中可以看到系統預設處理,是拒絕連線帶有可信機構頒發證書的HTTPS站點的,如下所示:

/**
  * Notify the host application that an SSL error occurred while loading a
  * resource. The host application must call either handler.cancel() or
  * handler.proceed(). Note that the decision may be retained for use in
  * response to future SSL errors. The default behavior is to cancel the
  * load.
  *
  * @param view The WebView that is initiating the callback.
  * @param handler An SslErrorHandler object that will handle the user's
  *            response.
  * @param error The SSL error object.
  */
 public void onReceivedSslError(WebView view, SslErrorHandler handler,
         SslError error) {
     // 拒絕連線
     handler.cancel();
 }

而我們重寫此方法的時候可以設定成接受所有連線,如下所示:

 public void onReceivedSslError(WebView view, SslErrorHandler handler,
         SslError error) {
     // 接受所有連線
    handler.proceed();
 }

參考:
https://blog.csdn.net/jogger_ling/article/details/60576625
https://blog.csdn.net/u012852986/article/details/78873387
https://blog.csdn.net/Hubert_bing/article/details/55258280