技术文章 | Android Webview场景下防止dns劫持的探索

本文来源于阿里云-云栖社区,原文点击这里


阿里云HTTPDNS是避免dns劫持的一种有效手段,在许多特殊场景如HTTPS/SNIokhttp等都有最佳实践,但在webview场景下却一直没完美的解决方案。

拦截方案是目前已知的一种在webview上应用httpdns的可行方案,本文从拦截方案的基本原理出发,尝试分析该方案背后存在的局限,并给出一些可行性上的建议。


基本原理


拦截方案是指通过对webview进行配置WebViewClient来做到对网络请求的拦截:

void setWebViewClient (WebViewClient client);

拦截方案的的调用流程如下图所示:


Webview相关的网络请求由系统的chromium网络库发起,Webview调用loadUrl方法时,chromium网络库会构造URLRequest实例,经过c层到java层,最终请求参数会回调给上层WebViewClientshouldInterceptRequest方法,而我们的目标是在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 getRequestHeaders();
}

相比之下WebResourceRequest能给的多了MethodHeader以及是否重定向,但是没有Body,也无法预知该请求是否可能携带body,对于带body的符合协议但非标的Get请求一样无法拦截,因此局限2:

 展开全文

你可能感兴趣的:(技术文章)