简体   繁体   English

无法设置WKWebView设置Cookie(iOS 11+)

[英]WKWebView setting Cookie not possible (iOS 11+)

I am desperately trying to add a custom cookie to a WKWebView instance (without using Javascript or similar workarounds). 我拼命试图将自定义cookie添加到WKWebView实例(不使用Javascript或类似的解决方法)。

From iOS 11 and upwards, Apple provides an API to do this: The WKWebView s WKWebsiteDataStore has a property httpCookieStore . 从iOS 11及更高版本开始,Apple提供了执行此操作的API: WKWebViewWKWebsiteDataStore具有属性httpCookieStore

Here is my (example) code: 这是我的(示例)代码:

import UIKit
import WebKit

class ViewController: UIViewController {

    var webView: WKWebView!

    override func viewDidLoad() {
        webView = WKWebView()
        view.addSubview(webView)
        super.viewDidLoad()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        let cookie = HTTPCookie(properties: [
            HTTPCookiePropertyKey.domain : "google.com",
            HTTPCookiePropertyKey.path : "/",
            HTTPCookiePropertyKey.secure : true,
            HTTPCookiePropertyKey.name : "someCookieKey",
            HTTPCookiePropertyKey.value : "someCookieValue"])!

        let cookieStore = webView.configuration.websiteDataStore.httpCookieStore
        cookieStore.setCookie(cookie) {
            DispatchQueue.main.async {
                self.webView.load(URLRequest(url: URL(string: "https://google.com")!))
            }
        }
    }

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()

        webView.frame = view.bounds
    }
}

After this, if I use webView.configuration.websiteDataStore.httpCookieStore.getAllCookies(completionHandler:) I see that my cookie is in the list of cookies. 此后,如果我使用webView.configuration.websiteDataStore.httpCookieStore.getAllCookies(completionHandler:)我会看到我的cookie在cookie列表中。

However, when inspecting the webview using Safari's developer tools (using a iOS Simulator of course) the cookie does not show up. 但是,当使用Safari的开发人员工具(当然使用iOS模拟器)检查Web视图时,cookie不会显示。

I also tried to inspect the traffic using a HTTP proxy (Charles in my case) to see if the cookie in included in my HTTP requests. 我还尝试使用HTTP代理(在本例中为Charles)检查流量,以查看cookie是否包含在我的HTTP请求中。 It is not. 它不是。

What am I doing wrong here? 我在这里做错了什么? How can I add a cookie to WKWebView (on iOS versions 11 and up)? 如何将cookie添加到WKWebView (在iOS 11及更高版本上)?

A bit late but I want to share a solution that worked for me, I hope it helps someone facing the same issue on iOS 12 as well. 有点晚了,但是我想分享一个对我有用的解决方案,希望它也可以帮助在iOS 12上也面临相同问题的人。

Here is the simplified workflow I used: 这是我使用的简化工作流程:

  1. Instantiate a WKWebsiteDataStore object 实例化WKWebsiteDataStore对象
  2. Set the custom cookie to its httpCookieStore 将自定义Cookie设置为其httpCookieStore
  3. Wait for the cookie to be set 等待cookie被设置
  4. Instantiate the WKWebView 实例化WKWebView
  5. Load the request 加载请求

To do that I have created an extension of WKWebViewConfiguration: 为此,我创建了WKWebViewConfiguration的扩展:

extension WKWebViewConfiguration {

static func includeCookie(cookie:HTTPCookie, preferences:WKPreferences, completion: @escaping (WKWebViewConfiguration?) -> Void) {
     let config = WKWebViewConfiguration()
     config.preferences = preferences

     let dataStore = WKWebsiteDataStore.nonPersistent()

     DispatchQueue.main.async {
        let waitGroup = DispatchGroup()

        waitGroup.enter()
        dataStore.httpCookieStore.setCookie(cookie) {
            waitGroup.leave()
        }

        waitGroup.notify(queue: DispatchQueue.main) {
            config.websiteDataStore = dataStore
            completion(config)
        }
    }
}

And for my example I have used it as follows: 对于我的示例,我使用它的方式如下:

override func viewDidLoad() {
  self.AddWebView()
}

private func addWebView(){

    let preferences = WKPreferences()
    preferences.javaScriptEnabled = true
    preferences.javaScriptCanOpenWindowsAutomatically = true

    let cookie = HTTPCookie(properties: [
        .domain: COOKIE_DOMAIN,
        .path: "/",
        .name: COOKIE_NAME,
        .value: myCookieValue,
        .secure: "TRUE",
        .expires: NSDate(timeIntervalSinceNow: 3600)
        ])

     //Makes sure the cookie is set before instantiating the webview and initiating the request
     if let myCookie = cookie {
        WKWebViewConfiguration.includeCookie(cookie: myCookie, preferences: preferences, completion: {
           [weak self] config in
              if let `self` = self {
                 if let configuration = config {
                    self.webView = WKWebView(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width , height: self.view.frame.height), configuration: configuration)

                    self.view.addSubview(self.webView)
                    self.webView.load(self.customRequest)
                 }
              }
     }
}

Any request to google.com redirects to www.google.com . google.com任何请求都将重定向到www.google.com

You would need to add www. 您将需要添加www. to the domain field of the cookie. 到cookie的domain字段。 If the domain or the path doesn't match the request, the cookie won't be sent. 如果域或路径与请求不匹配,则不会发送cookie。

You can add the cookies explicitly. 您可以显式添加cookie。

let url = URL(string: "https://www.google.com")!
var request = URLRequest(url: url)
if let cookies = HTTPCookieStorage.shared.cookies(for: url) {
    request.allHTTPHeaderFields = HTTPCookie.requestHeaderFields(with: cookies)
}
self.webView.load(request)

For iOS 11+ you really don't need to worry about cookies part it is very simple. 对于iOS 11或更高版本,您真的不需要担心cookie的一部分,这非常简单。 Create your cookie like this. 像这样创建您的cookie。 Don't make it secure true 不要确保它是真的

let newcookie = HTTPCookie(properties: [
        .domain: "domain",
        .path: "/",
        .name: "name",
        .value: "vale",
        .secure: "FALSE",
        .expires: NSDate(timeIntervalSinceNow: 31556926)
        ])!

self.webview.configuration.websiteDataStore.httpCookieStore.setCookie(newcookie, completionHandler: {
                        // completion load your url request here. Better to add cookie in Request as well. like this way
       request.addCookies()
//enable cookie through request
        request.httpShouldHandleCookies = true

//load request in your webview.


                    })

Request extention add after cookie value ";" 请求扩展在cookie值“;”之后添加

extension URLRequest {

internal mutating func addCookies() {
    var cookiesStr: String = ""

        let mutableRequest = ((self as NSURLRequest).mutableCopy() as? NSMutableURLRequest)!
            cookiesStr += cookie.name + "=" + cookie.value + ";"                

            mutableRequest.setValue(cookiesStr, forHTTPHeaderField: "Cookie")
            self = mutableRequest as URLRequest

     }

}

Also i can see your are not setting WKWebViewConfiguration of wkwebview. 我也可以看到您没有设置wkwebview的WKWebViewConfiguration。 Set configuration of your wkwebview. 设置您的wkwebview的配置。 Also implement WKHTTPCookieStoreObserver and implement function. 还实现WKHTTPCookieStoreObserver并实现功能。

    func cookiesDidChange(in cookieStore: WKHTTPCookieStore) {
    // Must implement otherwise wkwebview cookie not sync properly
    self.httpCookieStore.getAllCookies { (cookies) in
        cookies.forEach({ (cookie) in

        })
    }
}

Hope so this will work. 希望这样会起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM