我向url1发送了请求。 url1将使用cookie重定向到url2。 url2用于授权。我得到代码“302 found”,这是正确的。 但是当url2重定向回url1时,cookie丢失了。这导致我的请求保持重定向到url2,循环直到失败。
有没有人遇到过这种问题并知道解决方案?提前致谢。
这是一个WKWebView问题。 UIWebView可以正常工作。但不知何故,我需要改为使用WKWebView。
我已尝试过许多解决方案,例如Can I set the cookies to be used by a WKWebView?。这些方法可以处理同一域中的cookie。我的问题是url1和url2有不同的域名。重定向时,cookie丢失,导致授权失败,导致url1和url2之间的循环。
是否有人遇到此问题并找到了解决方法?提前谢谢。
答案 0 :(得分:6)
不幸的是,在WKWebView中没有官方支持处理302重定向响应。我也遇到了同样的问题。有一种方法可以解决,但可能会冒一些风险但不优雅。
WKWebView.load(_ request: URLRequest)
并使用URLSession代替发出请求。func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void)
以指定您不希望URLSession自动处理302重定向。URLSession
获得302响应后,附加的Cookie将自动设置为HTTPCookieStorage.shared
。然后使用这些Cookie和响应标头字段Location
的网址发出新请求由WKWebView
本身。代码示例是Here。我是WKWebView
的子类,并且在大多数情况下也处理cookie,包括你的302重定向案例。如果它适合你,请给我一个明星thx!
这是一种非常黑客的方式,如果你想在产品中使用它,请小心。
答案 1 :(得分:3)
如果您需要来自' url2'的后续请求要设置Cookie,您可以尝试使用' WKUserScript
'在文档开头通过javascript以编程方式设置值,如下所示:
WKUserContentController* userContentController = WKUserContentController.new;
WKUserScript * cookieScript = [[WKUserScript alloc]
initWithSource: @"document.cookie = 'TeskCookieKey1=TeskCookieValue1';document.cookie = 'TeskCookieKey2=TeskCookieValue2';"
injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
// again, use stringWithFormat: in the above line to inject your values programmatically
[userContentController addUserScript:cookieScript];
WKWebViewConfiguration* webViewConfig = WKWebViewConfiguration.new;
webViewConfig.userContentController = userContentController;
WKWebView * webView = [[WKWebView alloc] initWithFrame:CGRectMake(/*set your values*/) configuration:webViewConfig];
但是,如果您需要在初始加载请求中设置cookie,您可以在NSMutableURLRequest上设置它们,如下所示:
WKWebView * webView = /*initialization stuff*/
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"YOUR URL"]];
[request addValue:@"TestCookieKey1=TestCookieValue1;TestCookieKey2=TestCookieValue2;" forHTTPHeaderField:@"Cookie"];
// use stringWithFormat: in the above line to inject your values programmatically
[webView loadRequest:request];
您可以将上述两种技术结合起来,将Cookie值从Native环境传输到WebView环境。
您可以参考此link获取有关Cookie的更多高级信息。
答案 2 :(得分:2)
也许聚会晚了,但是上周我遇到了一个与上述问题非常接近的事情,而且从我的角度我得出结论,由于某些原因,WKWebView无法正确处理302响应上的cookie。
如果您的问题与我面临的问题类似:
您需要通过后续身份验证阶段所需的重定向传递一些cookie
然后,您可以轻松地将WKWebView与我在this gist中提供的WKWebView互换。
并按如下所示使用它:
let myWebView = SAWKWebView(frame: .zero)
...
myWebView.load(aRequest, handleRedirect: true, cookies: [myCookies])
cookies不是必需的,可以为零,具体取决于您的设置。
从WKWebView继承的SAWKWebView类,并且直接使用URLSession及其委托来解决上述问题。
通过这种方式,我可以依靠一种足够安全的方式闯入响应302(又名重定向)并使用HTTPStorageCookie手动处理Cookie,而无需依赖javascript和文档,因为根据我的经验,它并不总是可靠的。
执行所需的重定向后,我将内容呈现为HTML并根据需要继续。
答案 3 :(得分:0)
另一种解决方案对我有用:
采用WKNavigationDelegate
,webView.navigationDelegate = self
,然后:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
/// Cancel the navigation action
decisionHandler(.cancel)
/// Navigate yourself
let request = NSMutableURLRequest(url: url)
request.allHTTPHeaderFields = HTTPCookie.requestHeaderFields(with: Auth.getAuthCookies())
webView.load(request as URLRequest)
}
这是我的简单情况所需的全部,但是我想其他人可能还需要复制存储在navigationAction.request
中的其他请求信息,例如navigationAction.request.allHTTPHeaderFields
答案 4 :(得分:0)
我已经尝试了其他答案中提出的解决方案,但最终在我看来更好的解决方案是实现此WKNavigationDelegate的方法:
func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
if let url = webView.url {
webView.load(authenticatedRequest(URLRequest(url: url)))
}
}
authenticatedRequest()是给定请求的私有函数,它将返回带有标头/ cookies /无论您的服务需要进行身份验证的相同请求。
希望有人认为此解决方案有帮助。
答案 5 :(得分:0)
最近我遇到了同样的问题,并且通过执行此操作解决了这个问题。我确定只有在使用iOS <11的情况下,cookie丢失才会发生。为此,您需要像我最近应用的那样解决一些问题。
1-通过更新的cookie来响应服务器端的响应。无论何时从服务器更改
以这种方式从响应中读取Cookie。
if let allHttpHeaders = response.allHeaderFields as? [String: String] {
let cookies = HTTPCookie.cookies(withResponseHeaderFields: allHttpHeaders, for: responseUrl)
for cookie in cookies {
if cookie.name == "cookie name" {
// compare with old cookie value so it will show your cookie is changed now.
if "your_old_cookie_value" != cookie.value {
//update cookie in Script and request header
// reload your page here again.
break
}
}
}
}
这是最小的更改,可以解决Cookie丢失的问题,对于iOS> = 11应该不是问题,对于ios 11及更高版本,请使用 httpcookiestore
如果您有任何问题,请告诉我。
答案 6 :(得分:-2)
我认为iOS 11的正确解决方案是使用WKHTTPCookieStore。按照keynote的规定,它专门用于解决此问题。