思考 NSURLProtocol 无法拦截 WKWebview 请求的解决思路

1.hook XMLHTTPRequest

原理简单说就是 hook XMLHTTPRequest 的 send 方法和 open 函数,然后在里面重组 url 和 body 参数,然后重新发起请求,这边有个难点,就是 send 和 open 是异步的,所以需要等 hook 到 open 中的参数后再发起请求。

2.WKURLSchemeHandler

WKURLSchemeHandler 是 iOS11 就推出的,用于处理自定义请求的方案,不过并不能处理 HTTP、HTTPS 等常规 scheme。但是现在有另外一个方法,就是去 hook WKWebview 的 initWithFrame: 方法,然后在 hook 方法中设置一个 WKURLSchemeHandler 给 WKWebview 实例,这样就能截获 WKWebview 的 HTTP 和 HTTPS 请求了。范例如下

//
//  ViewController.m
//  WKWebviewURLSchemeHandlerProject
//
//  Created by jerrold on 2019/3/5.
//  Copyright © 2019 jerrold. All rights reserved.
//

#import "ViewController.h"
#import <WebKit/WebKit.h>

@interface CustomURLSchemeHandler : NSObject<WKURLSchemeHandler>
@end

@implementation CustomURLSchemeHandler
//这里拦截到URLScheme为customScheme的请求后,读取本地图片test.jpg,并返回给WKWebView显示
- (void)webView:(WKWebView *)webView startURLSchemeTask:(id<WKURLSchemeTask>)urlSchemeTask{
    NSURLRequest *request = urlSchemeTask.request;
    //在下面处理拦截到的HTTP和HTTPS请求,处理完后再次发起请求, 注意要处理didReceiveResponse:  didReceiveData: didFinish三个方法回调
    if ([request.URL.scheme containsString:@"https"]) {
        
    }else if ([request.URL.scheme containsString:@"http"]){
        
    }
//    UIImage *image = [UIImage imageNamed:@"test.jpg"];
//    NSData *data = UIImageJPEGRepresentation(image, 1.0);
//    NSURLResponse *response = [[NSURLResponse alloc] initWithURL:request.URL MIMEType:@"image/jpeg" expectedContentLength:data.length textEncodingName:nil];
//    [urlSchemeTask didReceiveResponse:response];
//    [urlSchemeTask didReceiveData:data];
//    [urlSchemeTask didFinish];
}


- (void)webView:(WKWebView *)webVie stopURLSchemeTask:(id)urlSchemeTask {
}
@end
@interface ViewController ()

@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //如下是以APP为视角写的处理WKWebview请求的方式,如果要AOP,就需要hook WKWebview的initwithFrame方法,在里面处理WKWebview的请求
    WKWebViewConfiguration *configuration = [WKWebViewConfiguration new];
    CustomURLSchemeHandler *handler = [[CustomURLSchemeHandler alloc]init];
    NSMutableDictionary *handlers = [configuration valueForKey:@"_urlSchemeHandlers"];
    handlers[@"https"] = handler;//修改handler,将HTTP和HTTPS也一起拦截
    handlers[@"http"] = handler;
    WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];
    self.view = webView;
    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.test.com"]]];
}
@end
复制代码

不过,这种方案和第一种有共性,就是利用了私有 API,很可能导致被 ban,毕竟 apple 最近审查非常严苛。但是起码比第一种方案好,不用担心 body 大小的问题,不用担心影响浏览器性能。

参考文献

1.WebKit で PrivateAPI 使って Proxy を実装する

2.Intercepting UIWebView & WKWebView — Custom URL Scheme handling

3.iOS 11 WKWebView 新特性


作者:Auditore
链接:https://juejin.im/post/5cac5046518825710d76c4e1
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值