# 4.浏览器的六种本地缓存

相同点:cookie,sessionStorage 和 localStorage 都是存储在浏览器端的。

不同点

  1. cookie数据始终在浏览器请求中被携带,在浏览器端和服务器端来回传递的;sessStorage 和 localStorage同属于 webStorage仅在本地保存,不会传递到服务器端
  2. 存活时间:cookie 在设置的存活时间之前一直有效sessionStorage在浏览器窗口关闭之前一直有效,localStorage 始终有效
  3. 存储大小:cookie 只有 4KB,sessionStorage 和 localStorage 存储空间大一些(大概 5Mb 左右
  4. 作用域:sessionStorage 不在不同的浏览器窗口中共享,即使同一个页面, 而 cookie 和 localStorage 在同源窗口(协议、域名、端口相同)中均共享
  5. 储存类型:webStorage 只能存字符串,无法直接存对象。cookie 存的是文本文件。
# 常用属性:
  • Secure => cookie 只有通过 HTTPS 加密过才能发送给服务端

    • 修改 cookie 时,domain 和 path 都相同才可以进行,有不同则创建一个新的 cookie
    • cookie 过期就会被浏览器删除
    • 有助于避免 XSS 攻击
  • HTTPOnly => 只允许通过请求访问 cookie,避免 document.cookie 方式攻击,有助于避免 CSRF 攻击

  • 二级域名能读取设置了 domain 为顶级域名或者自身的 cookie,不能读取其他二级域名 domain 的 cookie。例如:要想 cookie 在多个二级域名中共享,需要设置 domain 为顶级域名,这样就可以在所有二级域名里面或者到这个 cookie 的值了。

  • 顶级域名只能获取到 domain 设置为顶级域名的 cookie,domain 设置为其他子级域名的无法获取。

服务端一般都会给其设置一个过期时间 maxAge,短则 1 小时、1 天,长则 1 星期、1 个月甚至永久,这就是 Cookie 的生命(周期)。

Cookie 的存储形式,根据其生命周期的不同而不同。这由 maxAge 属性决定,共有这三种情况:

  1. maxAge > 0:cookie 不仅内存里有,还会持久化到硬盘,也叫持久 Cookie。这样的话即使你关机重启(甚至过几天再访问),这个 cookie 依旧存在,请求时依旧会携带
  2. maxAge < 0:一般值为-1,也就临时 Cookie。该 Cookie 只在内存中有(如 session 级别),一旦管理浏览器此 Cookie 将不复存在。值得注意的是:若使用无痕模式访问也是不会携带此 Cookie 的哟
  3. maxAge = 0:内存中没有,硬盘中也没有了,也就立即删除 Cookie。此种 case 存在的唯一目的:服务浏览器可能的已存在的 cookie,让其立马失效(消失) ❝Tips:请注意 maxAge<0(负数)和 maxAge=0 的区别。前者会存在于内存,只有关闭浏览器 or 重启才失效;后者是立即删除 ❞ 当然啦,Cookie 的生命周期除了受到后端设置的 Age 值来决定外,还有两种方式可“改变”它:

# 储存大量数据:IndexDB

# indexDB:

特性:

  1. 储存量理论没有上限
  2. 操作是异步的。 loaclStorage 是同步的。操作性能高
  3. 支持储存 JS 的对象
  4. 是正经的数据库,数据库能干的他都可以

缺点:

  1. 操作繁琐
  2. 本身有门槛

# 离线缓存:Application Cache

HTML5 引入了应用程序缓存(Application Cache),这意味着可对 web 应用进行缓存,并可在没有因特网连接时进行访问。

应用程序缓存为应用带来三个优势:

  1. 离线浏览 - 用户可在应用离线时使用它们
  2. 速度 - 已缓存资源加载得更快
  3. 减少服务器负载 - 浏览器将只从服务器下载更新过或更改过的资源

# 使用方式

<!DOCTYPE HTML>
<html manifest="demo.appcache">
...
</html>
1
2
3
4
  • 注意:manifest 文件需要设置正确的 MIME-type,即 "text/cache-manifest"。必须在 web 服务器上进行配置。
  • 注释:浏览器对缓存数据的容量限制可能不太一样(某些浏览器的限制是每个站点 5MB)。
  • 一旦文件被缓存,则浏览器会继续展示已缓存的版本,即使您修改了服务器上的文件。为了确保浏览器更新缓存,您需要更新 manifest 文件。

# 工作线程缓存:cacheStorage

  • 是在 service workers 规范中定义的,但可以用在其他工作线程
  • 主要用途是用于对请求的缓存

async function testCache{
    var cacheName = 'baidu'  // 定义cache名称
    var path = '/path'  // 定义路径

    var cachesMatch = await caches.match(path) // 匹配当前路径
    var cachesLocal = await caches.has(cacheName)

    //如果当前已有数据则直接获取缓存的数据
    if(cachesMatch && cachesLocal){
        caches.match(path).then(res => {
          return res.text()
        }).then(res => {
          console.log("获取cache数据: ", res)
        })
    }else{
      // 如果没有则获取远程数据
      getBaidu().then(res => {
        // 将请求的数据保存在caches中
        caches.open(cacheName).then(cache => {
          cache.put(path, new Response(JSON.stringify(res), { status: 200 }))          // 采用Json数据格式保存
        })
    })
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

结合 serviceWorker 和 cacheStorage 实现请求缓存 (opens new window)

# 应用场景

  1. cookie:标记用户与跟踪用户行为
  2. localStorage:长期保存在本地的数据(令牌)
  3. sessionStorage:敏感账号一次性登陆
  4. indexDB:储存大量数据、在线文档(富文本编辑器)、保存编辑历史。
  1. cookie 不安全,本地可以直接拿到
  2. session 访问多会占用服务器性能
  3. session 不支持分布式,会有负载均衡问题

要实现 Cookie 的跨域共享,有 3 个关键点:

  1. 服务端负责在响应中将 Set-Cookie 发出来(由 Access-Control-Allow-Credentials 响应头决定 设置 true)(服务端能正确的在响应中有Set-Cookie响应)
  2. 浏览器端只要响应里有 Set-Cookie 头,就将此 Cookie 存储(由异步对象的 XMLHttpRequest 对象的 withCredentials 属性决定 设置 true)
  3. 浏览器端发现只要有 Cookie,即使是跨域请求也将其带着(由异步对象的 withCredentials 属性决定) (当异步对象设置了withCredentials=true时,浏览器会保留下响应的 Cookie 等信息,并且下次发送请求时将其携带。因此要指示浏览器存储 Cookie 并且每次跨域请求都携带,仅需加上此参数,此时服务端的Access-Control-Allow-Origin这个响应头的值不能是通配符*,而只能是具体的值)
  1. Strict(禁止第三方 cookie)
  2. Lax 稍微严格一点
  3. None(Secure 必须为 true)

# CORS

  1. withCridential
  2. 后端配置Access-Control-Allow-Credentials

# 如果位于同个二级域名(SSO 单点登录)

  1. 将 cookie 存在二级域名下

# 降域

  1. 将某个二级域名的 path 设置跟另外一个域名相同

# nginx 反向代理

  1. proxy_cookie_domain 做 cookie 域名转换
  2. 转换 response 的 set-cookie header 中的 domain 选项,由后端设置的域名 domain 转换成你的域名 replacement
Last Updated: 6/3/2024, 1:08:34 AM