WKWebView请求添加Cookie

WKWebView发送请求时不会把HTTPCookieStorage中的cookie写入请求中需要手动添加。

iOS11之前实现思路是在原有的URLRequest中注入cookie再load,这种做法只能在webView第一次请求的时候会生效,后续未跨域请求带上cookie需要在WKWebViewConfiguration 中添加WKUserScript.

iOS11后通过WKWebsiteDataStore管理

func injectCookie(request: URLRequest) -> URLRequest {
        if #available(iOS 11.0, *) {
            return request
        }
        
        guard let url = request.url else {
            return request
        }

        var newRequest = URLRequest(url: url)
        let cookies = HTTPCookieStorage.shared.cookies ?? []
        var cookiesHeaders: [String] = []
        for cookie in cookies {
            if isNeedInjectCookie(url) {
                cookiesHeaders.append("\(cookie.name)=\(cookie.value)")
            }
        }
        let header = cookiesHeaders.joined(separator: ";")
        newRequest.addValue(header, forHTTPHeaderField: "Cookie")
        return newRequest
    }

//
private func injectCookie(configuration: WKWebViewConfiguration) {
        guard let url = self.request.url else { return }
        let cookies = HTTPCookieStorage.shared.cookies ?? []
        if #available(iOS 11.0, *) {
            let dataStore = WKWebsiteDataStore.nonPersistent()
            for cookie in cookies {
                dataStore.httpCookieStore.setCookie(cookie, completionHandler: nil)
            }
            configuration.websiteDataStore = dataStore
        } else {
            var cookieList: [String] = []
            for cookie in cookies {
                // 不写“path=/” cookie设置不生效
                cookieList.append("\(cookie.name)=\(cookie.value);path=/")
            }
            let cookieString = cookieList.joined(separator: ";")
            let cookieSource = "document.cookie = '\(cookieString)';"
            let cookieScript = WKUserScript(source: cookieSource, injectionTime: .atDocumentStart, forMainFrameOnly: false)
            configuration.userContentController.addUserScript(cookieScript)
        }
    }

通过上述方案修改后的cookie,服务器无法再往请求中添加cookie,所以服务器返回的cookie需要本地记录,后续请求再继续添加.

实现WKNavigationDelegate

func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        if #available(iOS 11.0, *)  {
            let cookieStore = webView.configuration.websiteDataStore.httpCookieStore
            cookieStore.getAllCookies { (cookies) in
                for cookie in cookies {
                    HTTPCookieStorage.shared.setCookie(cookie)
                }
            }
        } else {
            let httpResponse = navigationResponse.response as? HTTPURLResponse
            let headerFields = httpResponse?.allHeaderFields as? [String : String]
            if let headerFields = headerFields, let url = httpResponse?.url {
                let cookies = HTTPCookie.cookies(withResponseHeaderFields: headerFields, for: url)
                for cookie in cookies {
                    HTTPCookieStorage.shared.setCookie(cookie)
                }
            }
        }
        decisionHandler(.allow)
    }
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容