Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/108.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 正在从WKWebView获取所有Cookie_Ios_Swift_Uiwebview_Webkit_Wkwebview - Fatal编程技术网

Ios 正在从WKWebView获取所有Cookie

Ios 正在从WKWebView获取所有Cookie,ios,swift,uiwebview,webkit,wkwebview,Ios,Swift,Uiwebview,Webkit,Wkwebview,通过使用nshttpcookeStorage.sharedhttpcookeStorage(),从UIWebView获取cookie似乎很简单,但WKWebView似乎将cookie存储在其他地方 我做了一些研究,从NSHTTPURLResponse对象中获取了一些cookie。但是,这并不包含WKWebView使用的所有cookie: func webView(webView: WKWebView, decidePolicyForNavigationResponse navigationRes

通过使用
nshttpcookeStorage.sharedhttpcookeStorage()
,从
UIWebView
获取cookie似乎很简单,但
WKWebView
似乎将cookie存储在其他地方

我做了一些研究,从
NSHTTPURLResponse
对象中获取了一些cookie。但是,这并不包含
WKWebView
使用的所有cookie:

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)
      }
    }
  }
}
奇怪的是,ios 9中还有一个类
WKWebsiteDataStore
,负责管理
WKWebView
中的Cookie,但是,该类不包含检索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??
    }
  }
})
是否有获取cookie数据的解决方法?

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

问题在于
WKWebView
不会立即写回cookies。我认为它是按照自己的时间表来做的。例如,当
WKWebView
关闭或可能定期关闭时

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

通过关闭
WKWebView
,您可以强制“同步”到共享
NSHTTPCookieStorage
。请让我们知道这是否有效


更新:我刚刚记得,在年,我们强制
WKWebView
刷新其内部数据,包括cookie,方法是将其
WKProcessPool
替换为新的。没有官方的API,但我非常确定这是目前最可靠的解决方法。

提供了有关使用WKWebView处理cookie的有用信息。根据这一点,您应该能够使用标准的NSURLCache和NSHTTPCookie设置和检索cookie。他还提到根据Stephan的评论使用WKProccessPool。

正如Stefan提到的,cookies存储在
nshttpcookeStorage.sharedhttpcookeStorage()

但是,从我的实验中,我发现服务器设置的会话cookie对
nshttpcookestorage.sharedhttpcookestorage()
不可见


只要每个
WKWebView
共享同一个
WKProcessPool
实例,这些会话cookie将针对每个请求传递回服务器。如果您为
WKWebView
更改进程池,您实际上是在删除所有未来请求的会话cookie。

在实践中,我发现在“decidePolicyForNavigationResponse”方法中,您可以使用以下方法获取cookie,但遗憾的是,它不是会话的完整列表

let response = navigationResponse.response as! NSHTTPURLResponse
        let headFields = response.allHeaderFields as! [String:String]

        let cookies = NSHTTPCookie.cookiesWithResponseHeaderFields(headFields, forURL: response.URL!)

nshttpookie.cookiesWithResponseHeaderFields(headers,forURL:url)
中,如果设置cookie的url不是导航响应url(导致导航的url),会发生什么情况?我注意到设置cookies的回调url从未在navigationResponse的DecidePolicy中调用

func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
    let response = navigationResponse.response as! HTTPURLResponse
    let cookies  = HTTPCookie.cookies(withResponseHeaderFields: response.allHeaderFields as! [String : String], for: response.url!) 
}
由于回调本身不会导致页面导航,因此不会对回调url执行上述委托


最后,
httpCookieStore
的WKWebsiteDataStore
登陆iOS 11

详细信息
  • 代码9.2,Swift 4
  • 代码10.2(10E125),Swift 5
解决方案 用法 全样本 Info.plist

添加您的Info.plist传输安全设置

 <key>NSAppTransportSecurity</key>
 <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
 </dict>

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

  • 强制重置进程池:
-->这只适用于真正的设备

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

遵循Stefan Arentz和Phenom的答案。

我在Objective-C中使用了WKHTTPCookieStore,这对我获得持久性和会话cookie都很有效,但它只在iOS 11中有效+

在iOS 10和iOS 11中,通过替换Stefan的答案所述的WKProcessPool,强制WKWebView刷新其内部数据对我有效,但仅适用于持久cookie;正如J.Thoo所描述的那样,如果(@available(iOS 11.0,*)),会话cookie似乎会被删除{
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];
      }];
}
[webView.configuration.websiteDataStore.httpCookieStore getAllCookies:^(NSArray*_非空cookies){ NSURLRequest*请求= [[NSURLRequest alloc]initWithURL:self.URL];//您的URL NSURLSession*会话=[NSURLSession sharedSession]; NSURLSessionDataTask*task=[session dataTaskWithRequest:请求 completionHandler:^(NSData*responseData,NSURLRResponse*response, N错误*错误){ //做点什么 }]; [任务恢复]; [session.configuration.httpCookies存储库cookies:cookies for任务:任务]; }]; }
不要浪费时间从设备下方的iOS 11中提取cookie,成功的机会非常小。由于某些安全原因,Cookie提取可能会被阻止

请参阅以下日志:

2019-02-07 00:05:45.548880+0530 MyApp[2278:280725] [BoringSSL] nw_protocol_boringssl_get_output_frames(1301) [C8.1:2][0x10fd776f0] get output frames failed, state 8196

2019-02-07 00:05:45.550915+0530 MyApp[2278:280725] TIC Read Status [8:0x0]: 1:57
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        let cookieValue = HTTPCookieStorage.shared.cookies(for: navigationResponse.response.url!)
        print(cookieValue!)
        let response = navigationResponse.response as! HTTPURLResponse
        let headFields = response.allHeaderFields as! [String:String]

        let cookies = HTTPCookie.cookies(withResponseHeaderFields: headFields, for: response.url!)
        for cookie in cookies {
            print("name: \(cookie.name) value: \(cookie.value)")
        }
        decisionHandler(.allow)
    }
WKWebsiteDataStore.default().httpCookieStore.getAllCookies { (cookies) in
    for cookie in cookies {
        print(cookie)
    }
}
尝试为以下iOS 11设备生成的代码:

2019-02-07 00:05:45.548880+0530 MyApp[2278:280725] [BoringSSL] nw_protocol_boringssl_get_output_frames(1301) [C8.1:2][0x10fd776f0] get output frames failed, state 8196

2019-02-07 00:05:45.550915+0530 MyApp[2278:280725] TIC Read Status [8:0x0]: 1:57
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        let cookieValue = HTTPCookieStorage.shared.cookies(for: navigationResponse.response.url!)
        print(cookieValue!)
        let response = navigationResponse.response as! HTTPURLResponse
        let headFields = response.allHeaderFields as! [String:String]

        let cookies = HTTPCookie.cookies(withResponseHeaderFields: headFields, for: response.url!)
        for cookie in cookies {
            print("name: \(cookie.name) value: \(cookie.value)")
        }
        decisionHandler(.allow)
    }
WKWebsiteDataStore.default().httpCookieStore.getAllCookies { (cookies) in
    for cookie in cookies {
        print(cookie)
    }
}
上述代码将为您提供空cookie数组,因为由于某些安全原因,cookie提取被阻止

我建议您尝试以下适用于iOS 11及以上版本的选项:

2019-02-07 00:05:45.548880+0530 MyApp[2278:280725] [BoringSSL] nw_protocol_boringssl_get_output_frames(1301) [C8.1:2][0x10fd776f0] get output frames failed, state 8196

2019-02-07 00:05:45.550915+0530 MyApp[2278:280725] TIC Read Status [8:0x0]: 1:57
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        let cookieValue = HTTPCookieStorage.shared.cookies(for: navigationResponse.response.url!)
        print(cookieValue!)
        let response = navigationResponse.response as! HTTPURLResponse
        let headFields = response.allHeaderFields as! [String:String]

        let cookies = HTTPCookie.cookies(withResponseHeaderFields: headFields, for: response.url!)
        for cookie in cookies {
            print("name: \(cookie.name) value: \(cookie.value)")
        }
        decisionHandler(.allow)
    }
WKWebsiteDataStore.default().httpCookieStore.getAllCookies { (cookies) in
    for cookie in cookies {
        print(cookie)
    }
}

Swift 5

func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
    webView.configuration.websiteDataStore.httpCookieStore.getAllCookies { cookies in
        debugPrint(cookies.debugDescription)
    }

    decisionHandler(.allow)
}

对于iOS 11,不带任何扩展:

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

谢谢我去看看。您是否有对执行WKProcessPool开关的函数的引用?我是否要用一个新的池替换该池?是否有人体验过此答案中描述的解决方法?您所说的“关闭
WKWebView
”是什么意思?从SuperView中移除并将其设置为零?我需要有关WKWebView cookies的帮助。对于那些对此感到困惑的人,我确实做到了: