WKWebView setting Cookie not possible (iOS 11+)

纵然是瞬间 提交于 2019-12-01 12:24:58

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.

Here is the simplified workflow I used:

  1. Instantiate a WKWebsiteDataStore object
  2. Set the custom cookie to its httpCookieStore
  3. Wait for the cookie to be set
  4. Instantiate the WKWebView
  5. Load the request

To do that I have created an extension of 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.

You would need to add www. to the domain field of the cookie. If the domain or the path doesn't match the request, the cookie won't be sent.

You can add the cookies explicitly.

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. Create your cookie like this. 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 ";"

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. Set configuration of your wkwebview. Also implement WKHTTPCookieStoreObserver and implement function.

    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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!