从WKWebView获取所有cookie

apo*_*rat 58 webkit uiwebview ios swift wkwebview

虽然UIWebView通过使用来获取cookie 似乎很简单NSHTTPCookieStorage.sharedHTTPCookieStorage(),但它似乎WKWebView将cookie存储在其他地方.

我做了一些研究,然后我从NSHTTPURLResponse对象中抓取了一些饼干.但是,这并不包含以下所用的所有Cookie WKWebView:

func webView(webView: WKWebView, decidePolicyForNavigationResponse navigationResponse: WKNavigationResponse, decisionHandler: (WKNavigationResponsePolicy) -> Void) {

  if let httpResponse = navigationResponse.response as? NSHTTPURLResponse {
    if let headers = httpResponse.allHeaderFields as? [String: String], url = httpResponse.URL {
      let cookies = NSHTTPCookie.cookiesWithResponseHeaderFields(headers, forURL: url)

      for cookie in cookies {
        logDebug(cookie.description)

        logDebug("found cookie " + cookie.name + " " + cookie.value)
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

奇怪的是WKWebsiteDataStore,ios 9中还有一个负责管理cookie WKWebView的类,但是,该类不包含检索cookie数据的公共方法:

let storage = WKWebsiteDataStore.defaultDataStore()

storage.fetchDataRecordsOfTypes([WKWebsiteDataTypeCookies], completionHandler: { (records) -> Void in
  for record in records {
    logDebug("cookie record is " + record.debugDescription)

    for dataType in record.dataTypes {
      logDebug("data type is " + dataType.debugDescription)

      // get cookie data??
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

是否有获取cookie数据的解决方法?

Ste*_*ntz 65

由它使用(创建)的cookie WKWebView实际上是正确存储在NSHTTPCookieStorage.sharedHTTPCookieStorage().

问题是WKWebView不会立即回写cookie.我认为它按照自己的时间表来做到这一点.例如,当a WKWebView关闭或可能是周期性的.

所以最终他们最终会在那里,但是什么时候不可预测.

您可以NSHTTPCookieStorage通过关闭来强制"共享"到共享WKWebView.如果有效,请告诉我们.

更新:我只记得在Firefox for iOS中,我们强制WKWebView刷新其内部数据,包括cookie,用WKProcessPool新的替换它.没有官方API,但我很确定这是目前最可靠的解决方法.

  • 谢谢.我会检查一下.您是否有对执行该WKProcessPool开关的函数的引用?我只是用新的池替换游泳池吗? (7认同)
  • 对于那些看着这个并且困惑的人,我确实做了:`self.webView.configuration.processPool = [[WKProcessPool alloc] init];`并且它可以刷新cookie,因此它们在`NSHTTPCookieStorage.sharedHTTPCookieStorage()`中可用,但它只适用于我的设备,而不是模拟器. (6认同)

Tua*_*hou 17

最后,httpCookieStore对于WKWebsiteDataStore在iOS的11降落.

https://developer.apple.com/documentation/webkit/wkwebsitedatastore?changes=latest_minor


Vas*_*huk 17

细节

Xcode 9.2,Swift 4

extension WKWebView {

    private var httpCookieStore: WKHTTPCookieStore  { return WKWebsiteDataStore.default().httpCookieStore }

    func getCookies(for domain: String? = nil, completion: @escaping ([String : Any])->())  {
        var cookieDict = [String : AnyObject]()
        httpCookieStore.getAllCookies { cookies in
            for cookie in cookies {
                if let domain = domain {
                    if cookie.domain.contains(domain) {
                        cookieDict[cookie.name] = cookie.properties as AnyObject?
                    }
                } else {
                    cookieDict[cookie.name] = cookie.properties as AnyObject?
                }
            }
            completion(cookieDict)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法

// get cookies for domain
webView.getCookies(for: url.host) { data in
      print("=========================================")
      print("\(url.absoluteString)")
      print(data)
}

// get all cookies
webView.getCookies() { data in
      print("=========================================")
      print("\(url.absoluteString)")
      print(data)
}
Run Code Online (Sandbox Code Playgroud)

完整样本

  1. 不要忘记在此处添加解决方案代码
  2. ViewController嵌入了视图控制器
 <key>NSAppTransportSecurity</key>
 <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
 </dict>
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 它仅适用于iOS版本> = 11 (4认同)
  • 在ios 11之前的任何工作? (3认同)

小智 9

我知道这是一个非常古老的问题,我们有一个解决方案,但只适用于iOS 11和更高版本.对于那些正在处理iOS 10及更低版本(像我一样)的人,你可以考虑这种方法.它对我来说很完美:

  • 强制重置processPool:

extension WKWebView {
    func refreshCookies() {
        self.configuration.processPool = WKProcessPool()
        // TO DO: Save your cookies,...
    }
}
Run Code Online (Sandbox Code Playgroud)

- >这只适用于真实设备.

  • 对于模拟器,您应该添加:

func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
    if let response = navigationResponse.response as? HTTPURLResponse,
       let allHttpHeaders = response.allHeaderFields as? [String: String],
       let responseUrl = response.url {
        let cookies = HTTPCookie.cookies(withResponseHeaderFields: allHttpHeaders, for: responseUrl)

        for cookie in cookies {
            HTTPCookieStorage.shared.setCookie(cookie)
        }
    }

    decisionHandler(.allow)
}
Run Code Online (Sandbox Code Playgroud)

按照Stefan Arentz和Phenom的回答.


小智 5

if (@available(iOS 11.0, *)) {
  [webView.configuration.websiteDataStore.httpCookieStore
      getAllCookies:^(NSArray<NSHTTPCookie *> *_Nonnull cookies) {
        NSURLRequest *request =
            [[NSURLRequest alloc] initWithURL:self.URL]; //your URL
        NSURLSession *session = [NSURLSession sharedSession];
        NSURLSessionDataTask *task = [session
            dataTaskWithRequest:request
              completionHandler:^(NSData *responseData, NSURLResponse *response,
                                  NSError *error) {
                //Do Something
              }];
        [task resume];
        [session.configuration.HTTPCookieStorage storeCookies:cookies forTask:task];
      }];
}
Run Code Online (Sandbox Code Playgroud)


Zee*_*ro0 5

对于iOS 11,没有任何扩展:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    self.webView.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in
        for cookie in cookies {
            //...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)