【问题标题】:when redirect with code 302, WKWebView cannot set cookie使用代码 302 重定向时,WKWebView 无法设置 cookie
【发布时间】:2017-11-18 11:26:35
【问题描述】:

我向 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循环。

有没有人遇到过这个问题并找到了解决方法?提前致谢。

【问题讨论】:

标签: ios wkwebview


【解决方案1】:

如果您需要来自“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 的更多高级信息。

【讨论】:

  • 谢谢。如何在后续请求 url2 中注入 cookie?在“navigationAction”或“navigationResponse”中编写此用户脚本?我在其他堆栈溢出中看到了类似的答案。我很困惑哪个委托方法会更新 cookie?你能告诉我吗?
  • @T.W 你可以看一下这个 github repo 的代码。 github.com/haifengkao/YWebView 。它是一个带有持久性 cookie 的自定义 WKWebview 类。
  • @tek2 对不起。您的答案和 github repo 都无法解决此重定向问题。在我发布这个问题之前我已经尝试过了。
  • @T.W 我也遇到了同样的问题。 github repo 代码似乎适用于我的情况。
  • 在您的情况下,剂量 url1 和 url2 具有相同的域?还是不一样?就我而言,它们是不同的。
【解决方案2】:

不幸的是,在 WKWebView 中处理 302 重定向响应没有官方支持。我也遇到了同样的问题。有一种解决方法,但可能会冒一些风险,而且不优雅。

  1. 覆盖 WKWebView.load(_ request: URLRequest) 并改用 URLSession 发出请求。
  2. 确保您的 URLSession 可以自己处理 302 重定向,这意味着您需要实现 func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) 以指定您不希望 URLSession 自动处理 302 重定向。
  3. 一旦您使用URLSession 获得302 响应,附加的cookie 将自动设置为HTTPCookieStorage.shared。然后通过WKWebView 本身使用这些cookie 和响应标头字段Location 的URL 发出新请求。

代码示例是Here。我是WKWebView 的子类,并且在大多数情况下也处理cookie,包括您的302 重定向案例。如果它适合您,请给我一颗星谢谢!

这确实是一种 hack 方式,如果你想在产品中使用它,请小心。

【讨论】:

  • 您的 WKWebView 非常适合我从 UIWebView 到 WKWebView 的迁移。自从您发布此代码以来,您是否遇到过任何问题?谢谢你!
  • 非常感谢!
  • @Justin Domnitz 在 iOS9 下面的请求将被发送两次,而不是在 css/js 不工作的情况下调用loadHTMLString(也在源代码中注释)。我不确定它是否适合您的情况。
【解决方案3】:

我认为 iOS 11 的正确解决方案是使用 WKHTTPCookieStore。它旨在按照keynote 解决这个问题。

【讨论】:

    【解决方案4】:

    另一个解决方案对我有用:

    采用WKNavigationDelegatewebView.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

    【讨论】:

      【解决方案5】:

      我已经尝试了其他答案中建议的解决方案,但最后在我的情况下似乎效果更好的解决方案是实现这个 WKNavigationDelegate 的方法:

      func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
      
          if let url = webView.url {
              webView.load(authenticatedRequest(URLRequest(url: url)))
          }
      }
      

      authenticatedRequest() 是一个私有函数,它给定一个请求,它返回与标头/cookies/任何您的服务需要进行身份验证的相同请求。

      希望有人觉得这个解决方案有帮助。

      【讨论】:

        【解决方案6】:

        最近我遇到了同样的问题,我通过这样做解决了这个问题。我确信只有当你使用 iOS

        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

        如果您有任何问题,请告诉我。

        【讨论】:

          【解决方案7】:

          也许聚会迟到了,但上周我遇到了与上述问题非常接近的问题,而且从我的角度来看,我得出的结论是,出于某种原因,WKWebView 没有正确处理 302 响应上的 cookie。

          如果您的问题与我面临的问题相似:

          您需要从后续身份验证阶段所需的重定向传递一些 cookie

          然后您可以轻松地将您的 WKWebView 与我提供给 this gist 的 WKWebView 互换。

          并像下面这样使用它:

          let myWebView = SAWKWebView(frame: .zero)
          ...
          myWebView.load(aRequest, handleRedirect: true, cookies: [myCookies])
          

          cookies 不是必需的,可以为零,具体取决于您的设置。

          SAWKWebView 类继承自 WKWebView 并通过直接使用 URLSession 及其委托来解决上述问题。

          通过这种方式,我可以依靠一种足够安全的方式来闯入响应 302(又名重定向)并使用 HTTPStorageCookie 手动处理 cookie,而无需依赖 javascript 和文档,因为根据我的经验,它并不总是可靠的。

          执行所需的重定向后,我将内容呈现为 HTML 并根据需要继续。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-12-01
            • 2020-06-27
            • 2015-11-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-15
            相关资源
            最近更新 更多