玩转WKWebView网络请求:一份开发者指南
2023-12-15 18:18:15
众所周知,WKWebView 是一个独立进程,对于开发者来说,WKWebView 相当于一个黑盒。那么当开发者需要监控/接管 WKWebView 网络请求时,我们是否有方法可循呢?如果你也有这样的疑问,那请听我来为你一一解答。
1. 请求重定向
请求重定向是指当客户端发送请求后,服务器返回一个重定向响应,告知客户端需要将请求发送到另一个位置。WKWebView 默认会自动处理重定向请求,但如果开发者需要自定义重定向行为,可以通过以下步骤实现:
- 创建一个自定义的
WKURLRequestDelegate
类,并实现webView:didReceiveAuthenticationChallenge:completionHandler:
方法。 - 在
didReceiveAuthenticationChallenge
方法中,检查challenge.protectionSpace.authenticationMethod
是否为NSURLAuthenticationMethodServerTrust
。 - 如果是,则可以调用
completionHandler
方法来决定是否继续加载请求。
class CustomWKURLRequestDelegate: WKURLRequestDelegate {
func webView(_ webView: WKWebView, didReceiveAuthenticationChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, credential)
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
}
2. 请求拦截
请求拦截是指在请求发送到服务器之前对其进行拦截和修改。WKWebView 提供了两种拦截请求的方式:
- 使用
WKWebViewConfiguration.userContentController
属性来添加一个WKUserContentController
对象。 - 实现
WKUserContentControllerDelegate
协议中的webView:didReceiveScriptMessage:
方法。
class CustomWKUserContentControllerDelegate: WKUserContentControllerDelegate {
func webView(_ webView: WKWebView, didReceiveScriptMessage message: WKScriptMessage) {
if message.name == "interceptRequest" {
let requestData = message.body as! [String: Any]
let url = requestData["url"] as! String
let method = requestData["method"] as! String
let headers = requestData["headers"] as! [String: String]
let body = requestData["body"] as! String
// Modify the request as needed
let modifiedRequest = URLRequest(url: URL(string: url)!, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 10.0)
modifiedRequest.httpMethod = method
modifiedRequest.allHTTPHeaderFields = headers
modifiedRequest.httpBody = body.data(using: .utf8)
// Load the modified request
webView.load(modifiedRequest)
}
}
}
3. URL 重写
URL 重写是指将请求的 URL 重写为另一个 URL。WKWebView 提供了两种实现 URL 重写的方式:
- 使用
WKWebViewConfiguration.URLRewriteHandler
属性来设置一个WKURLRewriteHandler
对象。 - 实现
WKURLRewriteHandlerDelegate
协议中的rewriteRequestForMainFrame:
方法。
class CustomWKURLRewriteHandlerDelegate: WKURLRewriteHandlerDelegate {
func rewriteRequest(forMainFrame navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
let url = navigationAction.request.url!
if url.host == "example.com" {
let newURL = URL(string: "https://www.google.com")!
decisionHandler(.cancel)
webView.load(URLRequest(url: newURL))
} else {
decisionHandler(.allow)
}
}
}
4. 证书验证
当 WKWebView 加载一个使用 HTTPS 协议的网站时,它会验证服务器的证书。如果证书无效或不受信任,则 WKWebView 会显示一个警告。开发者可以通过以下步骤自定义证书验证行为:
- 创建一个自定义的
WKURLRequestDelegate
类,并实现webView:didReceiveAuthenticationChallenge:completionHandler:
方法。 - 在
didReceiveAuthenticationChallenge
方法中,检查challenge.protectionSpace.authenticationMethod
是否为NSURLAuthenticationMethodServerTrust
。 - 如果是,则可以调用
completionHandler
方法来决定是否继续加载请求。
class CustomWKURLRequestDelegate: WKURLRequestDelegate {
func webView(_ webView: WKWebView, didReceiveAuthenticationChallenge challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, credential)
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
}
5. 自签名证书
自签名证书是指由组织或个人自己颁发的证书,而不是由受信任的证书颁发机构 (CA) 颁发的。WKWebView 默认不会信任自签名证书,因此当加载一个使用自签名证书的网站时,它会显示一个警告。开发者可以通过以下步骤允许 WKWebView 信任自签名证书:
- 创建一个自定义的
WKWebViewConfiguration
对象。 - 将
WKWebViewConfiguration.allowsAirPlayForMediaPlayback
属性设置为true
。 - 将
WKWebViewConfiguration.allowsInlineMediaPlayback
属性设置为true
。
let configuration = WKWebViewConfiguration()
configuration.allowsAirPlayForMediaPlayback = true
configuration.allowsInlineMediaPlayback = true
let webView = WKWebView(frame: .zero, configuration: configuration)
6. 网络嗅探
网络嗅探是指捕获和分析网络流量。WKWebView 提供了一种内置的网络嗅探工具,可以用来捕获和分析 WKWebView 的网络流量。开发者可以通过以下步骤使用网络嗅探工具:
- 在 Safari 中打开开发者工具。
- 选择 "Network" 选项卡。
- 选中 "Preserve Log" 复选框。
- 加载一个网页。
- 网络嗅探工具会捕获和分析 WKWebView 的网络流量。
7. 网络代理
网络代理是指一个充当客户端和服务器之间中介的计算机。WKWebView 可以使用网络代理来修改请求和响应。开发者可以通过以下步骤使用网络代理:
- 创建一个自定义的
WKWebViewConfiguration
对象。 - 将
WKWebViewConfiguration.allowsAirPlayForMediaPlayback
属性设置为true
。 - 将
WKWebViewConfiguration.allowsInlineMediaPlayback
属性设置为true
。 - 将
WKWebViewConfiguration.allowsPictureInPictureMediaPlayback
属性设置为true
。
let configuration = WKWebViewConfiguration()
configuration.allowsAirPlayForMediaPlayback = true
configuration.allowsInlineMediaPlayback = true
configuration.allowsPictureInPictureMediaPlayback = true
let webView = WKWebView(frame: .zero, configuration: configuration)
8. charles
Charles 是一款流行的网络代理工具,可以用来捕获和分析网络流量。Charles 可以用来捕获和分析 WKWebView 的网络流量。开发者可以通过以下步骤使用 Charles 捕获和分析 WKWebView 的网络流量:
- 安装 Charles。
- 在 Charles 中设置代理。
- 在 WKWebView 中加载一个网页。
- Charles 会捕获和分析 WKWebView 的网络流量。
通过以上方法,开发者可以轻松掌控 WKWebView 的网络请求,从而满足各种开发需求。