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
<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的帮助。对于那些对此感到困惑的人,我确实做到了: