原理簡單說就是hook XMLHTTPRequest的send方法和open函數,而後在裏面重組url和body參數,而後從新發起請求,這邊有個難點,就是send和open是異步的,因此須要等hook到open中的參數後再發起請求。web
WKURLSchemeHandler是iOS11就推出的,用於處理自定義請求的方案,不過並不能處理HTTP、HTTPS等常規scheme。可是如今有另一個方法,就是去 WKWebview的initWithFrame:方法,而後設置一個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大小的問題,不用擔憂影響瀏覽器性能。bash
參考文獻app
1.WebKitでPrivateAPI使ってProxyを実裝する異步
2.Intercepting UIWebView & WKWebView — Custom URL Scheme handling函數