技術文章 | Android Webview場景下防止dns劫持的探索
阿新 • • 發佈:2019-01-10
本文來源於阿里雲-雲棲社群,原文點選這裡。
是避免dns劫持的一種有效手段,在許多特殊場景如、等都有最佳實踐,但在webview場景下卻一直沒完美的解決方案。
攔截方案是目前已知的一種在webview上應用httpdns的可行方案,本文從攔截方案的基本原理出發,嘗試分析該方案背後存在的侷限,並給出一些可行性上的建議。
基本原理
攔截方案是指通過對webview
進行配置WebViewClient
來做到對網路請求的攔截:
void setWebViewClient (WebViewClient client);
攔截方案的的呼叫流程如下圖所示:
Webview
相關的網路請求由系統的chromium網路庫發起,Webview
loadUrl
方法時,chromium網路庫會構造URLRequest
例項,經過c層到java層,最終請求引數會回撥給上層WebViewClient
的shouldInterceptRequest
方法,而我們的目標是在shouldInterceptRequest
方法中通過HTTPDNS進行URL中域名到ip的替換,並且構造和返回合法的WebResourceResponse
,讓webview在避免dns劫持的同時,也能正常地進行展示。
侷限
首先,當Android API < 21時,WebViewClient
提供的攔截API如下:
public WebResourceResponse shouldInterceptRequest (WebView view, String url);
此時shouldInterceptRequest
只能拿到URL,而請求方法、頭部等這些資訊是拿不到的,強行攔截會造成請求資訊的丟失,由此可知侷限1:
侷限1:Android API < 21只能攔截網路請求的URL,請求方法、請求頭等無法攔截;
其次,對於Android API >= 21的情況,其攔截API為:
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request);
第2個引數變成了WebResourceRequest
public interface WebResourceRequest {
Uri getUrl();
boolean isForMainFrame();
boolean isRedirect();
boolean hasGesture();
String getMethod();
Map<String, String> getRequestHeaders();
}
相比之下WebResourceRequest
能給的多了Method
,Header
以及是否重定向
,但是沒有Body
,也無法預知該請求是否可能攜帶body,對於帶body的符合協議但非標的Get請求一樣無法攔截,因此侷限2: