ChenYilong / ChenYilong/iOSBlog

iOS 防 DNS 污染方案调研(三)--- WebView 业务场景

Open
#11 10 comments 0 reactions 0 assignees View on GitHub
note
Dominant language
Objective-C
Stars
1.1k
Forks
184
PR merge metrics
No merged PRs in 30d

Description

# iOS防DNS污染方案调研---WebView业务场景

对应的GitHub仓库镜像地址在[这里](https://github.com/ChenYilong/iOSBlog/blob/master/Tips/DNS污染方案调研/iOS防DNS污染方案调研---WebView业务场景.md) ,欢迎提PR进行修改。

## 概述

本文主要介绍,防 DNS 污染方案在 WebView 场景下所遇到的一些问题,及解决方案,也会涉及比如:“HTTPS+SNI” 等场景。

## 面临的问题

/*one more thing*/

### WKWebView 无法使用 NSURLProtocol 拦截请求

方案如下:

1. 换用 UIWebView
2. 使用私有API进行注册拦截

换用 UIWebView 方案不做赘述,说明下使用私有API进行注册拦截的方法:

```Objective-C
//注册自己的protocol
[NSURLProtocol registerClass:[CustomProtocol class]];

//创建WKWebview
WKWebViewConfiguration * config = [[WKWebViewConfiguration alloc] init];
WKWebView * wkWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) configuration:config];
[wkWebView loadRequest:webViewReq];
[self.view addSubview:wkWebView];

//注册scheme
Class cls = NSClassFromString(@"WKBrowsingContextController");
SEL sel = NSSelectorFromString(@"registerSchemeForCustomProtocol:");
if ([cls respondsToSelector:sel]) {
// 通过http和https的请求,同理可通过其他的Scheme 但是要满足ULR Loading System
[cls performSelector:sel withObject:@"http"];
[cls performSelector:sel withObject:@"https"];
}

```

使用私有 API 的另一风险是兼容性问题,比如上面的 `browsingContextController` 就只能在 iOS 8.4 以后才能用,反注册 scheme 的方法 `unregisterSchemeForCustomProtocol:` 也是在 iOS 8.4 以后才被添加进来的,要支持 iOS 8.0 ~ 8.3 机型的话,只能通过动态生成字符串的方式拿到 `WKBrowsingContextController`,而且还不能反注册,不过这些问题都不大。至于向后兼容,这个也不用太担心,因为 iOS 发布新版本之前都会有开发者预览版的,那个时候再测一下也不迟。对于本文的例子来说,如果将来哪个 iOS 版本移除了这个 API,那很可能是因为官方提供了完整的解决方案,到那时候自然也不需要本文介绍的方法了。

注意避免执行太晚,如果在 `- (void)viewDidLoad` 中注册,可能会因为注册太晚,引发问题。建议在 `+load` 方法中执行。

然后同样会遇到 [《iOS SNI 场景下的防 DNS 污染方案调研》](https://github.com/ChenYilong/iOSBlog/issues/12) 里提到的各种 NSURLProtocol 相关的问题,可以参照里面的方法解决。

## Cookie相关问题

单独成篇: [《防 DNS 污染方案调研---iOS HTTPS(含SNI) 业务场景(四)-- Cookie 场景》]( https://github.com/ChenYilong/iOSBlog/issues/14 )

## 302重定向问题

上面提到的 Cookie 方案无法解决302请求的 Cookie 问题,比如,第一个请求是 http://www.a.com ,我们通过在 request header 里带上 Cookie 解决该请求的 Cookie 问题,接着页面302跳转到 http://www.b.com ,这个时候 http://www.b.com 这个请求就可能因为没有携带 cookie 而无法访问。当然,由于每一次页面跳转前都会调用回调函数:

```Objective-C
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;
```

可以在该回调函数里拦截302请求,copy request,在 request header 中带上 cookie 并重新 loadRequest。不过这种方法依然解决不了页面 iframe 跨域请求的 Cookie 问题,毕竟-[WKWebView loadRequest:]只适合加载 mainFrame 请求。

## 参考链接

**相关的库:**

- [GitHub:WebViewProxy](https://github.com/marcuswestin/WebViewProxy)
- [GitHub:NSURLProtocol-WebKitSupport](https://github.com/Yeatse/NSURLProtocol-WebKitSupport)
- [GitHub:happy-dns-objc](https://github.com/qiniu/happy-dns-objc)
- [Chrome For iOS ](https://chromium.googlesource.com/chromium/src.git/+/master/ios/)

**相关的文章:**

- [《NSURLProtocol对WKWebView的处理》]( http://www.jianshu.com/p/8f5e1082f5e0 )
- [《可能是最全的iOS端HttpDns集成方案》]( http://www.jianshu.com/p/cd4c1bf1fd5f )
- [《WKWebView 那些坑》]( https://zhuanlan.zhihu.com/p/24990222 )
- [《让 WKWebView 支持 NSURLProtocol》]( https://blog.yeatse.com/2016/10/26/support-nsurlprotocol-in-wkwebview/ )
- [《WKWebView的使用和各种坑的解决方法(OC+Swift)》](http://www.jianshu.com/p/403853b63537)

**可以参考的Demo:**

- [支持SNI与WebView的 alicloud-ios-demo](https://github.com/Dave1991/alicloud-ios-demo)
- [HybirdWKWebVIew](https://github.com/LiuShuoyu/HybirdWKWebVIew/)
- [《WWDC ​2017-WKWebView 新功能》]( https://zhuanlan.zhihu.com/p/27914128 )

## 走过的弯路

## 误以为 iOS11 新 API 可以原生拦截 WKWebView 的 HTTP/HTTPS 网络请求

参考:[Deal With WKWebView DNS pollution problem in iOS11](https://github.com/ChenYilong/iOS11AdaptationTips/issues/16)

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.