首页 > 解决方案 > WKNavigationResponse 不再通过其 response.header 提供对 cookie 的访问

问题描述

自推出以来,我一直在使用 WKWebView 而不是 UIWebView。我一直在使用委托方法 webView(decidePolicyFor navigationResponse) 函数来访问 navigationResponse 对象及其响应属性的 allHeaderFields 属性,以便从任何给定请求中读取 cookie。

public func webView(webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
    guard let response = navigationResponse.response as? HTTPURLResponse,
        let url = response.url,
        response.statusCode == 200,
        let headers = response.allHeaderFields as? [String: String] else {
            decisionHandler(.cancel)
            return
        }
        let cookies: NSArray = HTTPCookie.cookies(withResponseHeaderFields: headers, for: url) as NSArray

        for cookie in cookies {

            let aCookie = cookie as! HTTPCookie

            print("Background oAuth wkwebview response cookie: \(aCookie.name)")

            HTTPCookieStorage.shared.setCookie(aCookie)
        }

    decisionHandler(.allow)
}

直到上周,在 iOS 9-12(inc. beta 1-12&GM)中,如果响应的标头中有 cookie,则始终填充上述代码中的“cookie”。截至本周,随着 iOS 12 的发布,iOS 12 上的 cookie 始终为空。我在许多设备上对此进行了测试,但对于运行任何版本的 iOS 12 的任何设备,cookie 都无法访问。所有先前的设备固件版本仍按预期工作。

我有一台设备自发布以来一直使用 12 Beta 1 固件。直到本周,此代码在此设备上仍然有效。为什么在没有固件更新的情况下,iOS 12 上的 cookie 会突然停止访问?

标签: swiftcookieswebkitwkwebviewios12

解决方案


我能够通过利用新的 WKWebViewConfiguration 的 WebSiteDataStore 在 iOS 11+ 上获取 cookie 来解决这个问题

public func webView(webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
    guard let response = navigationResponse.response as? HTTPURLResponse,
        let url = response.url,
        response.statusCode == 200,
        let headers = response.allHeaderFields as? [String: String] else {
            decisionHandler(.cancel)
            return
    }
    let cookies: NSArray = HTTPCookie.cookies(withResponseHeaderFields: headers, for: url) as NSArray
    if #available(iOS 11.0, *) {
        webView.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in
            for aCookie in cookies {

                print("Background oAuth wkwebview response cookie: \(aCookie.name)")

                HTTPCookieStorage.shared.setCookie(aCookie)
            }

            decisionHandler(.allow)

        }
    } else {
        // Fallback on earlier versions
    }
}

推荐阅读