返回

玩转WKWebView网络请求:一份开发者指南

IOS

众所周知,WKWebView 是一个独立进程,对于开发者来说,WKWebView 相当于一个黑盒。那么当开发者需要监控/接管 WKWebView 网络请求时,我们是否有方法可循呢?如果你也有这样的疑问,那请听我来为你一一解答。

1. 请求重定向

请求重定向是指当客户端发送请求后,服务器返回一个重定向响应,告知客户端需要将请求发送到另一个位置。WKWebView 默认会自动处理重定向请求,但如果开发者需要自定义重定向行为,可以通过以下步骤实现:

  1. 创建一个自定义的 WKURLRequestDelegate 类,并实现 webView:didReceiveAuthenticationChallenge:completionHandler: 方法。
  2. didReceiveAuthenticationChallenge 方法中,检查 challenge.protectionSpace.authenticationMethod 是否为 NSURLAuthenticationMethodServerTrust
  3. 如果是,则可以调用 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 提供了两种拦截请求的方式:

  1. 使用 WKWebViewConfiguration.userContentController 属性来添加一个 WKUserContentController 对象。
  2. 实现 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 重写的方式:

  1. 使用 WKWebViewConfiguration.URLRewriteHandler 属性来设置一个 WKURLRewriteHandler 对象。
  2. 实现 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 会显示一个警告。开发者可以通过以下步骤自定义证书验证行为:

  1. 创建一个自定义的 WKURLRequestDelegate 类,并实现 webView:didReceiveAuthenticationChallenge:completionHandler: 方法。
  2. didReceiveAuthenticationChallenge 方法中,检查 challenge.protectionSpace.authenticationMethod 是否为 NSURLAuthenticationMethodServerTrust
  3. 如果是,则可以调用 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 信任自签名证书:

  1. 创建一个自定义的 WKWebViewConfiguration 对象。
  2. WKWebViewConfiguration.allowsAirPlayForMediaPlayback 属性设置为 true
  3. WKWebViewConfiguration.allowsInlineMediaPlayback 属性设置为 true
let configuration = WKWebViewConfiguration()
configuration.allowsAirPlayForMediaPlayback = true
configuration.allowsInlineMediaPlayback = true
let webView = WKWebView(frame: .zero, configuration: configuration)

6. 网络嗅探

网络嗅探是指捕获和分析网络流量。WKWebView 提供了一种内置的网络嗅探工具,可以用来捕获和分析 WKWebView 的网络流量。开发者可以通过以下步骤使用网络嗅探工具:

  1. 在 Safari 中打开开发者工具。
  2. 选择 "Network" 选项卡。
  3. 选中 "Preserve Log" 复选框。
  4. 加载一个网页。
  5. 网络嗅探工具会捕获和分析 WKWebView 的网络流量。

7. 网络代理

网络代理是指一个充当客户端和服务器之间中介的计算机。WKWebView 可以使用网络代理来修改请求和响应。开发者可以通过以下步骤使用网络代理:

  1. 创建一个自定义的 WKWebViewConfiguration 对象。
  2. WKWebViewConfiguration.allowsAirPlayForMediaPlayback 属性设置为 true
  3. WKWebViewConfiguration.allowsInlineMediaPlayback 属性设置为 true
  4. 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 的网络流量:

  1. 安装 Charles。
  2. 在 Charles 中设置代理。
  3. 在 WKWebView 中加载一个网页。
  4. Charles 会捕获和分析 WKWebView 的网络流量。

通过以上方法,开发者可以轻松掌控 WKWebView 的网络请求,从而满足各种开发需求。