今天看到阿里的mpass上有离线加载H5,简单研究了这里用WebKit的WKURLSchemeHandler那套,非NSURLProtocol,间接的跨域。其实拿来做逆向破解也不是不可以
主要code:
- (void)viewDidLoad {
[super viewDidLoad];
self.webHandler = [[MySchemeHandler alloc] init];
WKWebViewConfiguration *webViewConfiguration = [[WKWebViewConfiguration alloc] init];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"myScheme://myScheme.test.cn/index.html"] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10.0f];
[webViewConfiguration setURLSchemeHandler:self.webHandler forURLScheme:@"myScheme"];
[webViewConfiguration setURLSchemeHandler:self.webHandler forURLScheme:@"http"];
self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:webViewConfiguration];
[self.webView loadRequest:request];
[self.view addSubview:self.webView];
}
这里支持http、https的拦截
MySchemeHandler.m的主要代码:
- (void)webView:(nonnull WKWebView *)webView startURLSchemeTask:(nonnull id<WKURLSchemeTask>)urlSchemeTask {
NSLog(@"拦截到请求的URL:%@", urlSchemeTask.request.URL);
NSString *localFileName = [urlSchemeTask.request.URL lastPathComponent];
if([localFileName isEqualToString:@"getIp.php"]){
//拦截到的 http的XMLHttpRequest的异步请求
NSURLSessionDataTask *session = [[NSURLSession sharedSession] dataTaskWithRequest:urlSchemeTask.request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
[urlSchemeTask didReceiveResponse:response];
[urlSchemeTask didReceiveData:data];
[urlSchemeTask didFinish];
}];
[session resume];
return;
}
NSString *path = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"html"];
NSString *html = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
NSData *data = [html dataUsingEncoding:4];
NSString *fileMIME = [self getMIMETypeWithCAPIAtFilePath:path];
NSDictionary *responseHeader = @{
@"Content-type":fileMIME,
@"Content-length":[NSString stringWithFormat:@"%lu",(unsigned long)[data length]]
};
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@", @"myScheme://myScheme.test.cn/", @"index.html"]] statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:responseHeader];
[urlSchemeTask didReceiveResponse:response];
[urlSchemeTask didReceiveData:data];
[urlSchemeTask didFinish];
}
实现拦截http,https的拦截的主要代码:
CHDeclareClass(WKWebView)
CHClassMethod1(BOOL, WKWebView, handlesURLScheme, NSString *, urlScheme) {
if([urlScheme isEqualToString:@"http"] || [urlScheme isEqualToString:@"https"]) {
return NO;
}
return CHSuper1(WKWebView, handlesURLScheme, urlScheme);
}
__attribute__((constructor())) static void entry3() {
// 写到 XLWebViewConfiguration load 也可
CHLoadLateClass(WKWebView);
CHClassHook1(WKWebView, handlesURLScheme);
}
代码demo:https://github.com/LoveSVN/MySchemeHandler.git
最后的效果图: