美文网首页iOS
iOS - swift-WKWebView 同步多个cookie

iOS - swift-WKWebView 同步多个cookie

作者: 丿唯一的唯一丿 | 来源:发表于2018-05-03 14:41 被阅读663次

    笔者公司最近为了快速出一款app,采用UINavigationController+WebView或者NavigationController+UITabbarVC+WebView的方式,登录页面使用原APP,这样就不可避免的需要使用cookie与Html5交互(这里使用的WebViewJavascriptBridge)

    普通的webView 是通用 NSHTTPCookieStorage 里面的cookie
    所以set cookie 比较简单 这里不再重复

    WKWebView 拥有自己的私有存储,不会将 Cookie 存入到标准的 Cookie 容器 NSHTTPCookieStorage 所以需要自己储存一套 cookie 笔者是直接 在userdefaults

    func saveCookieWithDate(response:Response)->(){
      let headerFields = response.response?.allHeaderFields as! [String: String]
      let url = response.request?.url
      let cookies = HTTPCookie.cookies(withResponseHeaderFields: headerFields, for: url!)
      let cookieData = NSKeyedArchiver.archivedData(withRootObject: cookies)
      let cookieDictionary = ["cookie":cookieData] as [String : Any]
      let userDefaults = UserDefaults.standard
      userDefaults.set(cookieDictionary, forKey: CurrentUserCookie)
      userDefaults.synchronize()
    }
    

    实践发现 WKWebView 实例其实也会将 Cookie 存储于 NSHTTPCookieStorage 中,但存储时机有延迟,在iOS 8上,当页面跳转的时候,当前页面的 Cookie 会写入 NSHTTPCookieStorage 中,而在 iOS 10 上,JS 执行 document.cookie 或服务器 set-cookie 注入的 Cookie 会很快同步到 NSHTTPCookieStorage 中,FireFox 工程师曾建议通过 reset WKProcessPool 来触发 Cookie 同步到 NSHTTPCookieStorage 中,实践发现不起作用,并可能会引发当前页面 session cookie 丢失等问题。

    WKWebView Cookie 问题在于 WKWebView 发起的请求不会自动带上存储于 NSHTTPCookieStorage 容器中的 Cookie。

    这里先说一下百度来的资料

    1.load request 的时候添加cookie

     var urlRequest = URLRequest(url: url)
     urlRequest.addValue("testwkcookie = testwkcookievalue", forHTTPHeaderField: "Cookie")
     urlRequest.addValue("testwktoken = testwktokenvalue", forHTTPHeaderField: "Cookie")
    self.webView.load(urlRequest) 
    

    (无效)

    2.在WKUserContentController中,所有使用到WKUserScript。WKUserContentController是用于与JS交互的类,而所注入的JS是WKUserScript对象。

     let cookieString = "testwkcookie = testwkcookievalue; testToken = testwktokenvalue "
     let  cookieScript = WKUserScript(source: cookieString, injectionTime:     WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false)
    var userContent = WKUserContentController()
        userContent.addUserScript(cookieScript)
    

    (无效)

    到这里笔者已经浪费了 2个小时了(手动微笑)最后和 h5的小伙伴 问了 一下 cookie的加载地点 和 set时机 (他自己会手动修改这个)最后得到了答案:
    在通过 document.cookie 设置 Cookie 解决后续页面(同域)Ajax、iframe 请求的 Cookie 问题

    (但是 注意:document.cookie()无法跨域设置 cookie) 我们这里不涉及所以就忽略了

    let cookieString = "document.cookie = 'fromapp=ios';document.cookie = 'channel=appstore';"
    #warning 然而这里的单引号一定要注意是英文的,不要问我为什么告诉你这个(手动微笑)可以去看一下网页的cookie 格式
     let  cookieScript = WKUserScript(source: cookieString, injectionTime:         WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false)
    var userContent = WKUserContentController()
    userContent.addUserScript(cookieScript)
    

    成功 !!!

    最后贴一下 代码块 (直接复制就好了)

     func setWebCookie(userContent:WKUserContentController) {
        let userDefaults = UserDefaults.standard
        guard let cookieDictionary = userDefaults .object(forKey: hqCurrentUserCookie) as?Dictionary<String, Any> else {
            return
        }
        let cookieData = cookieDictionary["cookie"] as! Data
        guard let cookies = NSKeyedUnarchiver .unarchiveObject(with: cookieData ) as? [HTTPCookie] else
        {
            return
        }
        var cookieString = ""
        for cookie in cookies{
            cookieString.append("document.cookie =" + "'" + cookie.name + "=" + cookie.value + "';")
        }
    
        let  cookieScript = WKUserScript(source: cookieString, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false)
        userContent.addUserScript(cookieScript)
    }
    

    最后笔者又查到了一种 在iOS11中,苹果新增加了用于WKWebview Cookie存取操作的WKHTTPCookieStore。

    let cookie = HTTPCookie.init(properties: [
            .domain:"172.16.10.26",
            .path:"/src/p/index/index.html",
            .version:0,
            .expires:Date.init(timeIntervalSinceNow: 30*60*60),
            .name:"username",
            .value:"zhanggui33"
            ])
            
    let cookieStore = myWKWebView.configuration.websiteDataStore.httpCookieStore
    cookieStore.setCookie(cookie!) {
            self.myWKWebView.load(URLRequest.init(url: URL.init(string: "http://172.16.10.26:3333/src/p/index/index.html")!))
        }
    

    相关文章

      网友评论

        本文标题:iOS - swift-WKWebView 同步多个cookie

        本文链接:https://www.haomeiwen.com/subject/raxglftx.html