WKWebview注入cookie头导致redirect循环
我试图将我分别获得的会话cookie注入到WKWebview请求中,事实certificate这是相当痛苦的…
我设法使用这个解决scheme注入会话cookie,如下所示:
// Acquiring the cookies let cookies = HTTPCookie.cookies(withResponseHeaderFields: headers, for: s.request!.url!) //Appending all the cookies into one raw string. var cookiesRawString = "" for c in cookies { cookiesRawString += "\(c.name)=\(c.value); " } var req: URLRequest = try! URLRequest(url: URL, method: method) // Then the injection itself request.setValue(cookiesRawString, forHTTPHeaderField: "Cookie") webView.load(req)
让我快速用伪码解释服务器逻辑:
- 服务器用附加的初始会话cookie接收对端点/端点1的呼叫
- 然后继续将用户生成的令牌附加到url中,将客户端redirect到/ endpoint2 。
- 请求添加了令牌的第二个端点导致最终redirect到/ endpoint3并且带有包含一个时间会话cookie的Set-Cookie头
- / endpoint3添加一次会话cookie会导致200响应,并识别用户。
问题是,由于某种原因,当我使用上面的方法将cookies添加到初始请求时,会导致redirect循环,而在Android平台上,它的工作原理是完美的(我在那里使用了类似的注入方法)。
我看到他们之间的唯一区别是,Android应用程序只注入了初始请求 cookie,所有后续的redirect调用没有这些会话cookie。 虽然ios 在所有redirect调用上重复初始会话cookie (甚至忽略服务器set-cookie标头并附加初始会话cookie ..)。
难道我做错了什么? 我怎样才能让wkwebview仅在最初的请求中使用注入的cookie?
编辑1:也尝试回落到UIWebview,但它产生相同的结果,似乎注入cookie作为头不好,但我尝试使用HTTPCookieStorage, 但它不会保存cookies !
// the count is 7 var cookiesCount = HTTPCookieStorage.shared.cookies(for: s.request!.url!)?.count let cookies = HTTPCookie.cookies(withResponseHeaderFields: headers, for: s.request!.url!) for c in cookies { HTTPCookieStorage.shared.setCookie(c) } // Count is still 7! cookiesCount = HTTPCookieStorage.shared.cookies(for: s.request!.url!)?.count
编辑2:那么我发现UIWebview是使用cookie存储的全局实例,就像alamofire(我用来获取会话cookie)一样,所以不需要手动添加cookie,站点可以识别用户。
但是我仍然喜欢使用WKWebview,因为UIWebview内存泄露了天空火箭(在几个网页导航后超过100 MB)。
有没有办法在WKWebview中使用全局Cookie jar(由alamofire使用)?
我设法让WKWebview工作,使用一个hackish的解决scheme:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { let url = navigationAction.request.url!.absoluteString if UserAppendix.isLogin && url != previousNavigateUrl { previousNavigateUrl = url if url.contains("/endpoint1") { let headerFields = navigationAction.request.allHTTPHeaderFields let headerIsPresent = headerFields!.keys.contains("Cookie") if headerIsPresent { decisionHandler(WKNavigationActionPolicy.allow) } else { var req = URLRequest(url: navigationAction.request.url!) let cookies = NetworkAppendix.httpSessionCookies let values = HTTPCookie.requestHeaderFields(with: cookies) req.allHTTPHeaderFields = values webView.load(req) decisionHandler(WKNavigationActionPolicy.cancel) } } else if firstTime { firstTime = false let req = URLRequest(url: navigationAction.request.url!) webView.load(req) decisionHandler(WKNavigationActionPolicy.cancel) } else { decisionHandler(.allow) } } else { decisionHandler(.allow) } }
我在第一个请求上设置了cookie,并在第二个请求中断开stream程并创build一个新的请求(使用redirecturl),以避免我在第一个请求上设置的会话cookie,所有后续请求都被视为相同。
我知道这不是完美的,但它完成了工作。
我认为这可能是无关的,但我也有类似的问题。
原因是被修改的cookie使用NSURL.sharedSession搞乱了我所有的后续请求。 事实certificate,使用WKWebView的cookie设置是从NSURLSession.sharedSession中清除标题。 我认为cookie存储是跨多个会话共享的。 所以,我结束了使用EphemeralSession,而不是sharedSession。