我正试图将我单独获得的会话cookie注入到WKWebview请求中,这证明是相当痛苦的…
我设法使用这种解决方案注入会话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)
让我用伪代码快速解释一下服务器逻辑:
- 服务器接收到端点/endpoint1的呼叫,并附加初始会话cookie 然后将客户端重定向到/endpoint2,并在url中添加用户生成的令牌。
- 请求附加令牌的第二个端点最终重定向到/endpoint3,其中Set-Cookie头包含一次性会话cookie
- /endpoint3添加一次性会话cookie的结果为200响应,用户被识别。
问题是,由于某种原因,当我使用上述方法将cookie附加到初始请求时,它会导致重定向循环,而在Android平台上它工作完美无瑕(我在那里使用了类似的注入方法)。
我看到它们之间唯一的区别是android应用程序只在初始请求上注入cookie ,而所有随后的重定向调用都没有这些会话cookie。而ios 在所有重定向调用上重复初始会话cookie(甚至忽略server set-cookie头并附加初始会话cookie…)。我做错了什么吗?如何使wkwebview仅在初始请求时使用注入的cookie ?
编辑1:也尝试回落到UIWebview,但它产生相同的结果,似乎注入cookie作为头部是不好的,但我尝试使用HTTPCookieStorage, ,但它不会保存cookie !
// 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后几个网页导航!)。
是否有一种方法来使用全局cookie罐(alamofire使用)在WKWebview??
我认为这可能是无关的,但我有一个类似的问题。
原因是修改的cookie弄乱了我使用NSURL.sharedSession的所有后续请求。事实证明,使用WKWebView的cookie集正在从nsursession . sharedsession中清除header。我认为cookie存储是跨多个会话共享的。因此,我最终使用了EphemeralSession,而不是sharedSession。
我设法让它在WKWebview上工作,使用一个hack的解决方案:
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,在第二个请求上打破流并创建一个新请求(使用重定向url),为了避免我在第一个请求上设置的会话cookie,所有后续请求都被相同对待。
我知道这并不完美,但它可以完成工作。