http缓存机制
强缓存:
cache-control:
max-age:表示缓存有效时间
no-cache:表示不设置强缓存,可以走协商缓存
no-store:表示不设置缓存
public:表示所有用户都可以缓存资源,服务器和客户端
private:表示只有浏览器端可以缓存资源
expires:是一个时间字符串,代表资源失效时间
协商缓存:
etag/if-none-match 返回的是一个检验码,第一次请求返回资源时,服务器返回的头部中会加上etag,再次资源时,请求头中会携带if-none-match,其值就是响应头中返回的ETag的值;服务器判断是否命中缓存,命中,返回304,不返回资源,但是还是会返回etag
last-modified/last-modified-since 第一次请求返回资源时,服务器返回的头部中会加上last-modified,代表上一次修改时间,再次请求资源时,请求头中会携带last-modified-since,值是上一次返回的last-modified的值,服务器判断是否命中缓存,命中,返回304,不返回资源,也不返回last-modified
浏览器缓存分类
什么是http缓存
http缓存指的是:当客户端向服务器端请求资源的时候,会先到达浏览器缓存,如果浏览器缓存中存在这个资源的“副本”,就可以直接从浏览器缓存中读取,不需要在向服务器端获取这个资源。
常见的http缓存只能缓存get请求响应的资源,对其他的类型的响应无能为力,所以http缓存讨论的都是get请求响应的资源。
http缓存分类
强缓存
当浏览器去请求某个文件的时候,服务器在response header里面对文件做了缓存配置, response header 的cache-control,常见的设置是max-age public private no-cache no-store等
cache-control: max-age=xxxx,public
public的意思是客户端和代理服务器都可以缓存该资源
客户端在xxx秒的有效期内,如果发起了请求就去直接读缓存,返回状态200,如果用户做了刷新操作,就去请求服务器。
cache-control: max-age=xxxx,private
private的意思是只有客户端可以进行缓存
客户端在xxx秒的有效期内,如果发起了请求就去直接读缓存,返回状态200,如果用户做了刷新操作,就去请求服务器。
cache-control: max-age=xxxx,immutable(强缓存)
客户端在xxx秒的有效期内,如果发起请求就直接去读缓存,返回状态200,如果用户做了刷新操作也不会去请求服务器
cache-control: no-cache(不设置强缓存,不是字面意思的没有缓存)
跳过设置强缓存,但是不妨碍设置协商缓存
如果设置了强缓存,一般强缓存失效,才会去走协商缓存
但是设置了no-cache,就没有强缓存了,每次都会去请求服务器
cache-control: no-store
不缓存,没有强缓存或者协商缓存的说法
跟强制缓存相关的header头属性
协商缓存
上面说到的强缓存就是给资源设置一个过期时间,每次请求都去看过期了没有,如果过期了就去发送请求到服务器,如果没有过期就读取内存的数据。
这时候在去请求服务器的过程就可以设置协商缓存 response header里面的设置 这就是说,每次请求返回的response header的etag和last-modified,在下一次请求request header的时候都会带上,服务器把带过来的标识进行对比,如果没变就还是返回旧的,如果变了,就返回新的值。
对于客户端来说每次请求都要进行协商缓存了
发请求--->看资源是否过期--->过期--->请求服务器--->服务器对比是否真的过期--->没过期--->返回304 状态码--->客户端用缓存的资源
如果真的过期了,走下面这条路
发请求--->看资源是否过期--->过期--->请求服务器--->服务器对比是否真的过期--->过期--->返回200状态码--->客户端就向第一次请求资源一样,记录cache-control中的max-age、etag、last-modified的值
etag: '5c20abbd-e2e8' //可以理解成每个文件的id,唯一标识(实体标签)
last-modified: Mon, 24 Dec 2018 09:49:49 GMT // 上一次修改时间,精确到秒
思考💡: 为什么有etag?
主要解决last-modified的不足
1.一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新get;
2.某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),if-modified-since能检查到的粒度是秒级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
3.某些服务器不能精确的得到文件的最后修改时间。
跟协商缓存相关的header头属性有(ETag/If-Not-Match 、 Last-Modified/If-Modified-Since)请求头和 响应头需要成对出现
2种缓存的对比
为什么需要http缓存
1.减少了冗余数据的传输
2.缓解了服务器的压力,大大提高了网站的性能
3.加快了客户端加载网页的速度
【扩展】
http1.0时代:
强缓存:pragma、Expire
协商缓存:Last-Modified、if-Modified-Since
http1.1时代:
强缓存:Cache-Control
协商缓存:ETag、if-Not-Match
小结
1.强缓存,服务器通知浏览器设置一个过期时间,在缓存时间内请求资源,直接读取缓存,时间过期,走协商缓存
2.协商缓存,将协商缓存的关键字段ETag/Last-Modified通过请求发给服务器端,由服务器检验,返回304状态码直接读取缓存,返回200服务器返回新的资源
3.浏览器首次请求和再次发送http请求的流程图
cookie原理
什么是cookie?
cookie是一段文本信息,是以字符串的形式存在的。
cookie是服务器端给用户颁发的一个状态值,存储在客户端或者浏览器中,只要在cookie的有效期内,再次向服务器端发送请求时,浏览器会先检查本地的cookie,如果存在,会自动将cookie加在请求头部一起发给服务器端,服务器端通过cookie识别用户的身份,并且将存储在服务器端的资源返回给用户。
cookie机制:
如果没有在浏览器端设置cookie的过期时间,cookie保存在内存中,生命周期随着浏览器的关闭而结束,这种cookie简称回话cookie。如果设置了过期时间,cookie保存在硬盘中,关闭浏览器以后cookie还会存在,到过期时间才会消失。
cookie的实现思路
(1)用户第一次访问服务器端,服务器会通过Set-Cookie返回客户端,客户端将cookie存储在本地
(2)用户再次访问服务器端,会在本次查找cookie,如果存在会自动加到请求头中
(3)服务器端通过cookie识别用户的身份,返回对应的请求资源
cookie的缺点
单个cookie的存储大小不能超过4kb,大小受到限制
安全性较低,cookie欺骗、cookie截获
有些状态不可能保存在客户端
每次访问都要携带cookie给服务器,浪费带宽
cookie数据有路径的概念,可以限制cookie只属于某个路径下
服务器端的session机制
session机制
当服务器收到请求需要创建session对象时,首先会检查客户端请求中是否有sessionId,如果有id,服务器根据该id返回对应的session对象。 如果客户端请求中没有session对象,服务器会创建新的session对象,并且把sessionId在本次响应中返回给客户端。 通常使用cookie的方式把sessionId存储到客户端,如果用户禁用了cookie,则要使用URL重写,当浏览器支持cookie时,url不做任何处理,当浏览器不支持cookie的时候,将会重写URL将sessionId拼接到访问地址之后。
session的安全性大于cookie
session存储在cookie,要攻破session先攻破cookie
sessionId要有人登录,或者启动session_start才会有,所以攻破也不一定得到sessionId
第二次启动session_start后,前一次的sessionId就失效了,session过期以后,sessionId也就消失了
sessionId是加密的
session的缺点
session保存的东西越多,就越占用服务器内存,对于在线人数比较多的网站,服务器的压力比较大
依赖cookie,如果不支持cookie,就要进行url重写,不安全
过度使用session变量会导致代码不可读而且不好维护
token原理
token的实现思路:
(1)客户端提供username和password登录系统,服务器端通过mysql数据库做判断,
(2)用户存在,服务器端生成token返回
(3)用户请求服务器端接口api时,携带token
(4)服务器进行检验,如果匹配,返回请求数据
(5)如果不匹配,返回错误代码
区别cookie、session、token
(1)用户第一次通过username和password登录系统,服务器通过Set-Cookie返回客户端,客户端将cookie保存在本地,之后访问接口api携带cookie即可,
思考💡:但是服务器是怎么认证cookie的?
其实在服务器返回Set-Cookie的信息里,有一个sessionId,服务器会在本地保存一份sessionId,当客户端携带cookie过来时,就对比cookie中的sessionid和服务器自己保存的sessionId就知道你是谁了,所以说cookie是有状态的
(3)但是新的问题出现了,对于客户端自己保存自己的cookie没有问题,但是服务器端要保存所有的sessionId,随着数据访问量增大,服务器就会出现性能问题
(4)通过token来解决上述问题,还是老样子,第一次访问,服务器发token,但是服务器不会再存储了,因为对token的加密只有服务器知道算法和密钥,所以再一次访问,服务器拿到信息,对信息进行token计算,算出的token 和携带的token对比,发现匹配,就返回资源,这样就解决了服务器的压力,所以说token是无状态的。
本地存储对比
(1)cookie
cookie存储大小是4kb;当没有设置cookie的过期时间时,cookie存储在内存中,生命周期随着窗口关闭结束,这种称为回话cookie;当设置cookie过期时间时,cookie存在硬盘中,关闭浏览器cookie存在,到过期时间才会消失;cookie在服务器和浏览器端来回传递,sessionStorage和localStorage只存在于本地;cookie中保存的是字符串;
(2)sessionStorage
sessionStroage的大小是5MB;成为会话存储,内容存储在内存中,当关闭浏览器会消失;保存的是键值对,但是存储之前需要使用JSON.stringify()将对象转换为JSON 字符串,当取出使用的时候,使用JSON.parse()将JSON 字符串转成对象
(3)localStorage
localStorage的大小是5MB;是本地存储,内容存储在硬盘中,当关闭浏览器的时候还存在,除非手动删除,不然不会消失
说一说cookie sessionStorage localStorage 区别?
得分点💥
数据存储位置、生命周期、存储大小、写入方式、数据共享、发送请求是否携带、应用场景
标准回答 💥
Cookie、SessionStorage、 LocalStorage都是浏览器的本地存储。
它们的共同点:都是存储在浏览器本地的
它们的区别:
cookie是由服务器端写入的,而SessionStorage、 LocalStorage都是由前端写入的,
cookie的生命周期是由服务器端在写入的时候就设置好的,LocalStorage是写入就一直存在,除非手动清除,SessionStorage是页面关闭的时候就会自动清除。
cookie的存储空间比较小大概4KB,SessionStorage、 LocalStorage存储空间比较大,大概5M。
Cookie、SessionStorage、 LocalStorage数据共享都遵循同源原则,SessionStorage还限制必须是同一个页面。
在前端给后端发送请求的时候会自动携带Cookie中的数据,但是SessionStorage、 LocalStorage不会
加分回答 💥
由于它们的以上区别,所以它们的应用场景也不同,Cookie一般用于存储登录验证信息SessionID或者token,LocalStorage常用于存储不易变动的数据,减轻服务器的压力,SessionStorage可以用来检测用户是否是刷新进入页面,如音乐播放器恢复播放进度条的功能。