在 iOS 应用中更改 WKWebView 的来源

Posted

技术标签:

【中文标题】在 iOS 应用中更改 WKWebView 的来源【英文标题】:Change origin of WKWebView in iOS app 【发布时间】:2016-03-05 18:18:11 【问题描述】:

我有一个以 WKWebView 为中心的 ios 混合应用程序,使用 loadFileURL 加载本地网络资产。 WKWebView 通过 HTTPS 与带有 jQuery.ajax 的后端 API 通信。该应用程序仅限移动设备,我希望 API 也“仅限移动设备”。也就是说,我想阻止 Chrome 和 Firefox 等浏览器使用 API。

我的策略是在 API 响应中设置 Access-Control-Allow-Origin 标头,如下所示:

Access-Control-Allow-Origin: app://myApp

是否可以将WKWebView 的来源更改为app://myApp 以避免浏览器查询API?

【问题讨论】:

【参考方案1】:

案例:1

您可以在创建文档或完成加载文档时将 JS 注入 WKWebview,并将 java 脚本 XMLHTTPRequest open 方法与您的自定义实现挂钩,以便为来自 WKWebView 的所有 AJAX 请求添加此自定义标头。

示例代码

NSString *XMLHTTPRequestHookJSPath = [[NSBundle mainBundle] pathForResource:@"XMLHTTPRequestHook.js" ofType:nil];
NSString *kXMLHTTPRequestHookJS = [NSString stringWithContentsOfFile:XMLHTTPRequestHookJSPath encoding:NSUTF8StringEncoding error:NULL];
WKUserContentController *contentController = [[WKUserContentController alloc] init];
WKUserScript *script = [[WKUserScript alloc] initWithSource:kXMLHTTPRequestHookJS injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO];
[contentController addUserScript:script];
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = contentController;

self.lastUsedWebView = [[WKWebView alloc] initWithFrame:self.webContainerView.bounds configuration:configuration];
self.lastUsedWebView.navigationDelegate = self;

在 XMLHTTPRequestHook.js 中尝试将 XMLHttpRequest 与您的自定义实现挂钩,以添加此自定义标头并回调原始打开方法。

案例 2 如果您希望在 WKWebview 中加载 URLRequest 时添加此标头,您可以按如下方式将此标头添加到 NSMutableRequest 并在 WKWebview 中加载此请求。但是,使用此方法,您可能在 WKWebview 的所有 AJAX 调用中都没有此标头。

示例代码:

WKWebView * webView = /*set up your webView*/
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com/index.html"]];
[request addValue:@"app://myApp" forHTTPHeaderField:@"Access-Control-Allow-Origin"];

// use stringWithFormat: in the above line to inject your values programmatically
[webView loadRequest:request];

希望这会有所帮助。

【讨论】:

嗨,钱德拉。在应用程序方面,我希望更改 originAccess-Control-Allow-Origin 标头由 API 服务器响应添加! 嗨..如果您正在寻找类似 NSURLProtocol 的东西来拦截来自 WKWebview 的网络请求,NSURLProtocol 不适用于 WKWebview,因为 WKWebview 会加载来自不同进程的所有网络请求。但是,您仍然可以尝试在 case1 中提到的解决方案,将来自 WKWebview 的所有 AJAX 调用的标头更改为所需的值,看看是否有帮助。 另外,您可以更改策略并为来自 WKWebView 的所有 AJAX 调用添加自定义标头(而不是使用 Access-Control-Allow-Origin 标头),您可以在 API 服务器中使用此自定义标头以识别 api 调用来自您的应用程序,而不是来自任何其他浏览器。如果有帮助,请告诉我。 浏览器可以使用 javascript 添加客户标头。从安全角度来看,除非您对 CORS OPTIONS 预检的延迟感到满意,否则这无济于事,我现在就是这样。

以上是关于在 iOS 应用中更改 WKWebView 的来源的主要内容,如果未能解决你的问题,请参考以下文章

iOS 9 WKWebView 产生“加载资源失败:已取消”,而 iOS 8 没有

如何在 iOS 应用程序 WkWebView 中调试 javascript?

iOS H5 容器的一些探究:UIWebView 和 WKWebView 的比较和选择

iOS 端容器之 WKWebView 那些事

iOS 端容器之 WKWebView 那些事

iOS 13 beta 中 WKWebView 的内在内容大小问题