Cookie 是什么?
Cookie 是浏览器访问服务器后,服务器传给浏览器的一段数据。
它有以下几个特点:
- 服务器通过 Set-Cookie 响应头设置 Cookie(给浏览器的一串字符串)
例如,response.setHeader('Set-Cookie', `sign_in_email=${email}`)
- 浏览器得到 Cookie 之后,以后每次浏览器向服务器发送 HTTP 请求时,每个请求都会带上相应的 Cookie
- 服务器通过读取浏览器的 Cookie 就可以知道登录用户的信息(识别用户身份)
- 浏览器要在一段时间内保存这个 Cookie(Cookie 存储在本地浏览器上)
- Cookie 默认在用户关闭页面后就失效(和 sessionStorage 一样),但是可以通过后台代码任意设置 Cookie 的过期时间(Expires,Max-Age)
- 一般来说,单个域名设置的 Cookie 不应超过30个,每个 Cookie 的大小不能超过4KB。
Cookie 的用途
- 对话(session)管理:保存登录、购物车等需要记录的信息。
- 个性化:保存用户的偏好,比如网页的字体大小、背景色等等。
- 追踪:记录和分析用户行为。
Cookie 有关问题
- Cookie 存在哪?
在 Windows 系统中, Cookie 是存放在 C 盘的一个文件中 - Cookie可以被用户篡改吗?
可以;通过用户手动修改或通过 JS 修改(document.cookie
) - Cookie 遵守同源策略吗?
浏览器的同源政策规定,两个网址只要域名相同和端口相同,就可以共享 Cookie(不要求协议相同)
举例来说,当请求 qq.com 下的资源时,浏览器会默认带上 qq.com 对应的 Cookie,不会带上 baidu.com 对应的 Cookie;
当请求 v.qq.com 下的资源时,浏览器不仅会带上 v.qq.com 的Cookie,还会带上 qq.com 的 Cookie;
另外 Cookie 还可以根据路径做限制,这个功能用得比较少。 - Cookie 如何设置过期时间?
用 Max-Age 或 Expires 都可以设置 Cookie 的过期时间;
Expires属性指定一个具体的到期时间,Max-Age 属性指定从现在开始 Cookie 存在的秒数。同时指定了 Expires 和 Max-Age,那么Max-Age 的值将优先生效。 - 如何删除 Cookie?
删除一个现存 Cookie 的唯一方法,是设置它的 expires 属性为一个过去的日期。
document.cookie = 'fontSize=;expires=Thu, 01-Jan-1970 00:00:01 GMT';
上面代码中,名为 fontSize 的 Cookie 的值为空,过期时间设为1970年1月1月零点,就等同于删除了这个 Cookie。
Cookie 存在的一个很大的问题就是用户可以随意篡改 Cookie,很不安全,因此需要通过设置 Session 来防止用户篡改
Session
Session 和 Cookie 的作用有点类似,都是为了存储用户相关的信息。服务器通过 Cookie 给用户一个 SessionID,这个 SessionID 对应服务器里面的一小块内存,每次用户访问服务器时,服务器就通过用户对应的 SessionID 去读取对应的 Session,从而知道用户的隐私信息。
Session 的优点是比 Cookie 安全,缺点是相比较于 cookie 来说内存占用比较大
- 服务器将 SessionID(随机数)通过 Cookie 发送给浏览器
- 浏览器访问服务器时,服务器读取的是 SessionID
- 服务器有一块内存(哈希表)保存了所有的 Session
- 通过 SessionID 我们可以得到对应用户的隐私信息,如 id、email 等
- 这块内存(哈希表)就是服务器上的所有 Session(s)(用户只有一个 Session,服务器有很多个 Session)
localStorage (本地存储)
localStorage 是 HTML5 提供的 API,用于脚本在浏览器保存数据。sessionStorage 保存的数据用于浏览器的一次会话(session),当会话结束(通常是窗口关闭)时,数据被清空;localStorage保存的数据长期存在,下一次访问该网站的时候,网页可以直接读取以前保存的数据。
localStorage 是一种持久化的存储方式。在以前没有 localStorage 时,所有变量在页面刷新时全部销毁,没有办法保留下来。
- localStorage 跟 HTTP 无关
- HTTP 不会带上 localStorage 的值
- 只有相同域名的页面才能互相读取 ;ocalStorage(没有同源那么严格)
- 每个域名的 localStorage 容量是有限的,每个域名 localStorage 最大存储量为 5Mb 左右(每个浏览器不一样)
- 常用场景:用来记录是否已经提示过用户(记录一些没有用的信息,不能用来记录密码)
let already = localStorage.getItem('已经提示了')
if (!already) {
alert('Welcome!')
localStorage.setItem('已经提示了', true)
} else {} // 重复刷新时,只会提示一次"Welcome!"
- localStorage 永久有效,除非用户清理缓存
注意:Session 和 localStorage 本质上都是哈希表,但区别在于 Session 是服务器上的 hash 表,而 localStorage 是浏览器上的 hash 表,且只能存储字符串。
localStorage 的几个常用的 API
localStorage.clear()
方法用于清除所有保存的数据。该方法的返回值是undefined。
sessionStorage(会话存储)
sessionStorage 与 localStorage 相似,唯一的不同之处在于保存期限的长短不同。
sessionStorage 保存的数据用于浏览器的一次会话(session),当会话结束(通常是窗口关闭),数据被清空;localStorage 保存的数据长期存在,下一次访问该网站的时候,网页可以直接读取以前保存的数据。
HTTP 缓存
使用 HTTP 缓存有利于 web 性能优化
1. Cache-Control(缓存控制)
Cache-Control 可以让浏览器在一定时间内不访问服务器(不发请求),直接使用本地的缓存作为响应,这样做可以有效避免很多不必要的 HTTP 请求,从而改善页面的性能。
Cache-Control 使用 max-age 指定组件被缓存多久,从请求开始在 max-age 时间内浏览器使用缓存,max-age 时间之外的使用请求。
response.setHeader('Catch-Control','max-age=315360000')
问:为什么首页不能设置 Cache-Control?
答:如果对首页也进行缓存,那么用户刷新之后不会发起请求,无法得到更新后的资源。
问:如何更新缓存?
答:由于只有相同的 URL 才能加载缓存,因此加一个查询参数即可实现更新缓存,重新发起请求
例如,<script src="./main.js?v=2"></script>
在一个原本加载本地缓存的 JS 中加一个查询字符串?v=2
,即可让这个JS 文件重新发起请求
2. Expire
Expires 响应头包含日期/时间, 即在此时候之后,响应过期。
Expires: Wed, 21 Oct 2015 07:28:00 GMT
Expires 和 Cache-Control 的区别:
- Expires 是以前用来控制缓存的 HTTP 头,Cache-Control 是 Expires 的升级版
- Cache-Control 设置的是时间长度,而 Expire 是设置时间点
- 如果两个都设置了,优先使用 Cache-Control,而 Expires 头会被忽略
3. MD5 和 ETag
- MD5 是一种消息摘要算法,可以把微小的差异放大,用于确保信息传输完整一致。
- ETag 是 HTTP 响应头中的内容,可以让缓存更高效。如果内容没有改变,服务器不需要发送完整的响应。而如果内容发生了变化,使用 ETag 有助于防止资源的同时更新相互覆盖。
那么具体是如何实现的呢,这里举一个例子说明
请求一个main.js文件
查看响应
请求
以后每次请求的版本号如果和 If-None-Match 的值相同,就返回状态码 304,且不需要下载响应体
HTTP 304 Not Modified 表示无需再次传输请求的内容,也就是说可以使用缓存的内容
总结
- Cookie、Session、Cache-Control 都是在服务器的响应头中设置的
- Session 与 Cookie 的区别与联系
区别:
- Session 存储在服务器,而 Cookie 是存储在本地浏览器。
- Cookie 不安全,Session 比较安全。
- Session 占用服务器的内存比较大,Cookie 保存在本地不占用服务器资源。
联系:
一般来说,Session 基于 Cookie 来实现,其 Session ID 是通过 Cookie 发送给客户端的。
但 Session 也可以用 LocalStorage + 查询参数实现(不基于 Cookie)
- Cookie 和 localStorage 的区别
- Cookie会自动被上传到服务器,而 LocalStorage 只存在于本地的浏览器上,不会「自动」被上传到服务器(LocalStorage 不会随 HTTP 发给 Server)。
- 它们所支持的最大存储空间不同,LocalStorage 的大小限制比 Cookie 大多了。
- localStorage 和 sessionStorage 的区别
保存期限的长短不同;localStorage 里面存储的数据没有过期时间设置,而存储在 sessionStorage 里面的数据在页面会话结束(页面关闭)时会被清除。
简单地说,localStorage 不会自动过期,sessionStorage 在会话结束时会自动过期。 - 前端永远不要 读/写 Cookie(用 localStorage)
-
Cache-Control: max-age=1000
缓存 与 ETag 的「缓存」有什么区别?
Cache-Control 是直接不请求(1000 秒内),读取本地缓存作为响应;而 ETag 只是不下载响应体(响应体为空,沿用之前的响应体),但依然会发起请求。