iOS - swift-WKWebView 同步多个cookie

笔者公司最近为了快速出一款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 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)