WKWebview 注入 cookie header 导致重定向循环
WKWebview injecting cookie header cause redirect loop
我正在尝试将我单独获取的 session cookie 注入到 WKWebview 请求中,结果证明这很痛苦...
我设法使用 this solution 注入 session 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)
让我用伪代码快速解释一下服务器逻辑:
- 服务器收到对端点 /端点 1 的调用,并附加了初始 session cookies
- 然后继续将客户端重定向到 /endpoint2,并在 url.
中附加用户生成的令牌
- 请求附加令牌的第二个端点导致最终重定向到 /endpoint3,Set-Cookie header 包含一次 session cookie
- /endpoint3 附加一次 session cookie 导致 200 响应,用户被识别。
问题是,由于某种原因,当我使用上述方法将 cookie 附加到初始请求时,会导致重定向循环,而在 Android 平台上它可以完美运行(我在那里使用类似的注入方法)。
我看到它们之间的唯一区别是 android 应用程序仅在初始请求时 注入 cookies ,而所有后续的重定向调用都没有这些session 饼干。
虽然 ios 在所有重定向调用 上重复初始 session cookie(甚至忽略服务器 set-cookie header 并附加初始session 饼干..).
我是不是做错了什么?如何让 wkwebview 仅在初始请求时使用注入的 cookie?
编辑 1:也尝试回退到 UIWebview,但它产生相同的结果,似乎将 cookie 作为 header 注入并不好,但我尝试使用 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 相同(我用它来获取 session cookie),因此无需手动添加 cookie,该站点认出了用户。
但我仍然更喜欢使用 WKWebview,因为 UIWebview 内存泄漏飞速上升(几个网页导航后超过 100 MB!)。
有没有办法在WKWebview中使用全局cookie jar(alamofire使用的)?
我设法让它在 WKWebview 上运行,使用了一个 hackish 解决方案:
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,所有后续请求都被相同对待。
我知道它并不完美,但它完成了工作。
我认为这可能无关,但我遇到了类似的问题。
原因是修改后的 cookie 弄乱了我使用 NSURL.sharedSession 的所有后续请求。事实证明,使用 WKWebView 设置的 cookie 正在从 NSURLSession.sharedSession 中清除 headers。我认为 cookie 存储在多个会话之间共享。所以,我最终使用了 EphemeralSession,而不是 sharedSession。
我正在尝试将我单独获取的 session cookie 注入到 WKWebview 请求中,结果证明这很痛苦...
我设法使用 this solution 注入 session 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)
让我用伪代码快速解释一下服务器逻辑:
- 服务器收到对端点 /端点 1 的调用,并附加了初始 session cookies
- 然后继续将客户端重定向到 /endpoint2,并在 url. 中附加用户生成的令牌
- 请求附加令牌的第二个端点导致最终重定向到 /endpoint3,Set-Cookie header 包含一次 session cookie
- /endpoint3 附加一次 session cookie 导致 200 响应,用户被识别。
问题是,由于某种原因,当我使用上述方法将 cookie 附加到初始请求时,会导致重定向循环,而在 Android 平台上它可以完美运行(我在那里使用类似的注入方法)。
我看到它们之间的唯一区别是 android 应用程序仅在初始请求时 注入 cookies ,而所有后续的重定向调用都没有这些session 饼干。 虽然 ios 在所有重定向调用 上重复初始 session cookie(甚至忽略服务器 set-cookie header 并附加初始session 饼干..).
我是不是做错了什么?如何让 wkwebview 仅在初始请求时使用注入的 cookie?
编辑 1:也尝试回退到 UIWebview,但它产生相同的结果,似乎将 cookie 作为 header 注入并不好,但我尝试使用 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 相同(我用它来获取 session cookie),因此无需手动添加 cookie,该站点认出了用户。
但我仍然更喜欢使用 WKWebview,因为 UIWebview 内存泄漏飞速上升(几个网页导航后超过 100 MB!)。
有没有办法在WKWebview中使用全局cookie jar(alamofire使用的)?
我设法让它在 WKWebview 上运行,使用了一个 hackish 解决方案:
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,所有后续请求都被相同对待。
我知道它并不完美,但它完成了工作。
我认为这可能无关,但我遇到了类似的问题。
原因是修改后的 cookie 弄乱了我使用 NSURL.sharedSession 的所有后续请求。事实证明,使用 WKWebView 设置的 cookie 正在从 NSURLSession.sharedSession 中清除 headers。我认为 cookie 存储在多个会话之间共享。所以,我最终使用了 EphemeralSession,而不是 sharedSession。