# 4.浏览器的六种本地缓存
# 储存少量数据: cookie,sessionStorage 和 localStorage
相同点:cookie,sessionStorage 和 localStorage 都是存储在浏览器端的。
不同点:
- cookie数据始终在浏览器请求中被携带,在浏览器端和服务器端来回传递的;sessStorage 和 localStorage同属于 webStorage,仅在本地保存,不会传递到服务器端
- 存活时间:cookie 在设置的存活时间之前一直有效,sessionStorage在浏览器窗口关闭之前一直有效,localStorage 始终有效
- 存储大小:cookie 只有 4KB,sessionStorage 和 localStorage 存储空间大一些(大概 5Mb 左右)
- 作用域:sessionStorage 不在不同的浏览器窗口中共享,即使同一个页面, 而 cookie 和 localStorage 在同源窗口(协议、域名、端口相同)中均共享
- 储存类型:webStorage 只能存字符串,无法直接存对象。cookie 存的是文本文件。
# 1.1 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 设置为其他子级域名的无法获取。
# Cookie 的生命周期
服务端一般都会给其设置一个过期时间 maxAge,短则 1 小时、1 天,长则 1 星期、1 个月甚至永久,这就是 Cookie 的生命(周期)。
Cookie 的存储形式,根据其生命周期的不同而不同。这由 maxAge 属性决定,共有这三种情况:
- maxAge > 0:cookie 不仅内存里有,还会持久化到硬盘,也叫持久 Cookie。这样的话即使你关机重启(甚至过几天再访问),这个 cookie 依旧存在,请求时依旧会携带
- maxAge < 0:一般值为-1,也就临时 Cookie。该 Cookie 只在内存中有(如 session 级别),一旦管理浏览器此 Cookie 将不复存在。值得注意的是:若使用无痕模式访问也是不会携带此 Cookie 的哟
- maxAge = 0:内存中没有,硬盘中也没有了,也就立即删除 Cookie。此种 case 存在的唯一目的:服务浏览器可能的已存在的 cookie,让其立马失效(消失) ❝Tips:请注意 maxAge<0(负数)和 maxAge=0 的区别。前者会存在于内存,只有关闭浏览器 or 重启才失效;后者是立即删除 ❞ 当然啦,Cookie 的生命周期除了受到后端设置的 Age 值来决定外,还有两种方式可“改变”它:
# 储存大量数据:IndexDB
# indexDB:
特性:
- 储存量理论没有上限
- 操作是异步的。 loaclStorage 是同步的。操作性能高
- 支持储存 JS 的对象
- 是正经的数据库,数据库能干的他都可以
缺点:
- 操作繁琐
- 本身有门槛
# 离线缓存:Application Cache
HTML5 引入了应用程序缓存(Application Cache),这意味着可对 web 应用进行缓存,并可在没有因特网连接时进行访问。
应用程序缓存为应用带来三个优势:
- 离线浏览 - 用户可在应用离线时使用它们
- 速度 - 已缓存资源加载得更快
- 减少服务器负载 - 浏览器将只从服务器下载更新过或更改过的资源
# 使用方式
<!DOCTYPE HTML>
<html manifest="demo.appcache">
...
</html>
1
2
3
4
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
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)
# 应用场景
- cookie:标记用户与跟踪用户行为
- localStorage:长期保存在本地的数据(令牌)
- sessionStorage:敏感账号一次性登陆
- indexDB:储存大量数据、在线文档(富文本编辑器)、保存编辑历史。
# 四、 cookie 和 session 的问题
- cookie 不安全,本地可以直接拿到
- session 访问多会占用服务器性能
- session 不支持分布式,会有负载均衡问题
# Cookie 的跨域共享
要实现 Cookie 的跨域共享,有 3 个关键点:
- 服务端负责在响应中将 Set-Cookie 发出来(由 Access-Control-Allow-Credentials 响应头决定 设置 true)(服务端能正确的在响应中有Set-Cookie响应)
- 浏览器端只要响应里有 Set-Cookie 头,就将此 Cookie 存储(由异步对象的 XMLHttpRequest 对象的 withCredentials 属性决定 设置 true)
- 浏览器端发现只要有 Cookie,即使是跨域请求也将其带着(由异步对象的 withCredentials 属性决定) (当异步对象设置了withCredentials=true时,浏览器会保留下响应的 Cookie 等信息,并且下次发送请求时将其携带。因此要指示浏览器存储 Cookie 并且每次跨域请求都携带,仅需加上此参数,此时服务端的Access-Control-Allow-Origin这个响应头的值不能是通配符*,而只能是具体的值)
# 浏览器 cookie 的 same-site
- Strict(禁止第三方 cookie)
- Lax 稍微严格一点
- None(Secure 必须为 true)
# CORS
- withCridential
- 后端配置
Access-Control-Allow-Credentials
# 如果位于同个二级域名(SSO 单点登录)
- 将 cookie 存在二级域名下
# 降域
- 将某个二级域名的 path 设置跟另外一个域名相同
# nginx 反向代理
- proxy_cookie_domain 做 cookie 域名转换
- 转换 response 的 set-cookie header 中的 domain 选项,由后端设置的域名 domain 转换成你的域名 replacement