WKWebview缓存不能更新

Cookie和Session概述

1、Cookie

Cookie是客户端请求服务端时,服务器会将一些信息以键值对的形式返回给客户端,保存在浏览器中,后续交互的时候可以带上这些Cookie值。用Cookie就可以方便的做一些缓存。

Cookie的缺点是大小和数量都有限制;Cookie是存在客户端的可能被禁用、删除、篡改,是不安全的;Cookie如果很大,每次要请求都要带上,这样就影响了传输效率。

Cookie的内容主要包括:名字,值,过期时间,路径和域;路径与域一起构成Cookie的作用范围。若不设置过期时间,则表示这个Cookie的生命期为浏览器会话期间,关闭浏览器窗口,Cookie就消失。这种生命期为浏览器会话期的Cookie被称为会话Cookie。会话Cookie一般不存储在硬盘上而是保存在内存里。

若设置了过期时间,浏览器就会把Cookie保存到硬盘上,关闭后再次打开浏览器,这些Cookie仍然有效直到超过设定的过期时间。存储在硬盘上的Cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存里的Cookie,不同的浏览器有不同的处理方式 。

2、Session

Session是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。

当Server程序要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session id,如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个);如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。

保存这个session id的方式可以采用Cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。一般这个cookie的名字都是类似于SEEESIONID。但Cookie可以被人为的禁止,则必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。

经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面。还有一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。

首次 WKWebView 请求不携带 Cookie 的问题

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

目前许多 H5 业务都依赖于 Cookie 作登录态校验,如果登陆是在 WebView 里做的,不会有什么问题;但是在很多场景下,在Native做登录,需要将登录信息带给WebView;但是在Native做了登录,也获取了Cookie信息,也使用 NSHTTPCookieStorage 将Cookie存到了本地;但是WKWebView在打开时候,不会自动去NSHTTPCookieStorage获取Cookie信息,这就是著名的首次 WKWebView 请求不携带 Cookie 的问题。

WKWebView 实例其实会将 Cookie 存储于 NSHTTPCookieStorage 中,但存储时机有延迟,在iOS 8上,当页面跳转的时候,当前页面的 Cookie 会写入 NSHTTPCookieStorage 中,而在 iOS 10 上,JS 执行 document.cookie 或服务器 set-cookie 注入的 Cookie 会很快同步到 NSHTTPCookieStorage 中

不携带 Cookie 的问题解决方法

Javascript注入CookieWKWebView的Cookie注入

首先获取到cookie:

NSArray *cookies = [[NSHTTPCookieStoragesharedHTTPCookieStorage] cookies];

JS注入缓存

1:通过 document.cookie 设置 Cookie (JS注入)解决后续页面(同域)Ajax、iframe 请求的 Cookie 问题;但是会遇到跨域丢失的问题

2:无法解决302请求的Cookie问题,假设第一个请求是 www.a.com,我们通过在 request header 里带上 Cookie 解决该请求的 Cookie 问题,接着页面302跳转到 www.b.com,这个时候 www.b.com 这个请求就可能因为没有携带 cookie 而无法访问。

3:每一次页面跳转前都会调用回调函数decidePolicyForNavigationAction, 在这里拦截302请求,copy request,在 request header 中带上 cookie 并重新 loadRequest。

但是这种方法依然解决不了页面 iframe 跨域请求的 Cookie 问题,毕竟-[WKWebView loadRequest:]只适合加载 mainFrame 请求。

WKHTTPCookieStore (iOS 11 later)之后解决方法

WKWebView每次请求都会携带 WKHTTPCookieStore 里的 Cookie。(WKWebView 使用 NSURLProtocol 拦截请求无法获取 Cookie 信息)。在执行 [WKWebView loadRequest:] 前将 NSHTTPCookieStorage中的Cookie信息复制到 WKHTTPCookieStore 中,以此来达到 WKWebView中注入Cookie 的目的。示例代码如下:

iOS11之后解决方法

多WKWebView实例共享Cookie

Session 级别的 cookie 是保存在 WKProcessPool 里的,每个 WKWebview 都可以关联一个 WKProcessPool 的实例,如果需要在整个 App 生命周期里访问 h5 保留 h5 里的登录状态的,可以将使用 WKProcessPool 的单例来共享登录状态

让所有 WKWebView 共享同一个 WKProcessPool 实例,可以实现多个 WKWebView 之间共享 Cookie(session Cookie and persistent Cookie) 数据。不过 WKWebView WKProcessPool 实例在 App 杀进程重启后会被重置,导致 WKProcessPool 中的 Cookie、session Cookie 数据丢失,目前也无法实现 WKProcessPool 实例本地化保存

你可能感兴趣的:(WKWebview缓存不能更新)