HTTP的缓存控制和Cookie机制

952 阅读5分钟

HTTP缓存

缓存控制(强制缓存)

  1. 浏览器发送请求,向服务端请求资源
  2. 服务器做出响应并返回携带有效期的资源
  3. 浏览器缓存资源用于重用

HTTP/1.1定义的Cache-Control头用来区分对缓存机制的支持情况,Request HeadersResponse Headers都支持这个属性,通过它提供的不同的值来定义缓存策略:

  • Cache-Control: no-store

    • 缓存中不得存储任何关于客户端请求和服务端响应的内容
    • 每次由客户端发起的请求都会下载完整的响应内容
    • 用于某些变化非常频繁的数据,例如秒杀页面,实时排行榜等
  • Cache-Control: no-cache

    • 允许缓存但需要重新验证,每次使用之前需要去服务器端验证,请求中所描述的缓存是否过期,若未过期返回304 Not Modified,使用本地缓存副本
  • Cache-Control: private

    • 只允许客户端(浏览器)使用的私有缓存
  • Cache-Control: public

    • 允许服务器(中间代理、CDN等等)及客户端使用的的缓存
  • Cache-Control: max-age=31536000

    • 缓存的生存时间设置(从响应报文的创建时开始计算,包含了在链路传输过程中所有节点所停留的时间)
  • Cache-Control: must-revalidate

    • 如果缓存不过期就可以继续使用,过期了还想用就必须去服务器验证

条件请求(协商缓存)

浏览器用Cache-Control做缓存控制只能是刷新数据,不能很好地利用缓存数据,又因为缓存会失效,使用前还必须要去服务器验证是否是最新版

浏览器可以用两个连续的请求组成验证动作

  1. 先是一个 HEAD,获取资源的修改时间等元信息
  2. 然后与缓存数据比较,如果没有改动就使用缓存,节省网络流量
  3. 否则就再发一个 GET 请求,获取最新的版本

但这样的两个请求网络成本太高了,所以HTTP协议就定义了一系列If开头的条件请求字段,由服务器检查验证资源是否过期,把两个请求才能完成的工作合并在一个请求里做:

  • If-Modified-Since/If-Unmodified-Since配合Last-modified
  • If-Match/If-None-Match配合ETag
  • If-Range字段值中既可以用Last-Modified时间值用作验证,也可以用ETag标记作为验证,但不能将两者同时使用

需要第一次的响应报文预先提供Last-modifiedETag,然后第二次请求时就可以带上缓存里的原值,验证资源是否是最新的,如果资源没有变,服务器就回应一个304 Not Modified,表示缓存依然有效,浏览器就可以更新一下有效期继续使用

  • Last-modified
    • 文件的最后修改时间
  • ETag
    • Entity Tag 资源唯一标识,解决修改时间无法准确区分文件变化的问题
      • 一个文件在一秒内修改了多次,但因为修改时间是秒级,所以这一秒内的新版本无法区分
      • 一个文件定期更新,但有时会是同样的内容,实际上没有变化,用修改时间就会误以为发生了变化,传送给浏览器就会浪费带宽

ETag 还有 之分:

  • 强 ETag 要求资源在字节级别必须完全相符
  • 弱 ETag 在值前有个“W/”标记,只要求资源在语义上没有变化,但内部可能会有部分发生了改变(例如 HTML 里的标签顺序调整,或者多了几个空格)

Cookie

工作过程

用户通过首次通过浏览器向服务端发送请求,此时的身份是未知的,服务器不能知道用户是谁,所以会利用Set-Cookie字段,以key=value的格式随着Response Headers发送给浏览器

浏览器根据服务端发送来的Set-Cookie身份标识内容,将Cookie保存,再次发送请求时就会在Request Headers中携带此信息

服务器在某些场景下会设置多个Set-Cookie,浏览器发送时不需要设置多个,用;隔开就可以了

时效

  • Expires

    • 过期时间,使用绝对时间点,例如:expires=Wed, 02 Dec 2020 03:07:26 GMT;
  • Max-Age

    • 用的是相对时间,单位是秒,浏览器用收到报文的时间点再加上 Max-Age,就可以得到失效的绝对时间

ExpiresMax-Age 可以同时出现,两者的失效时间可以一致,也可以不一致,但浏览器会优先采用 Max-Age 计算失效期

作用域

  • Domain 所属域名
  • Path 所属路径

浏览器发送Cookie时会提取URI中的hostpath进行对比,只有满足条件的情况下才会发送

安全性

  • HttpOnly
    • 浏览器中的js引擎通过document.cookie读取Cookie数据,可以利用XSS 跨站脚本的方式进行攻击,HttpOnly会告知浏览器只能使用HTTP协议传输Cookie,浏览器会禁用掉有关Cookie操作的所有api
  • SameSite
    • 预防XCRF 跨站请求伪造
    • SameSite=Strict:严格禁止Cookie随跳转链接进行跨站发送
    • SameSite=Lax:允许 GET/HEAD 等安全方法,禁止POST跨站发送
  • Secure
    • Cookie只能用HTTPS协议加密传输,明文的HTTP协议禁止发送(Cookie本身不是加密的,在浏览器中以明文方式存储)

浏览器中Cookie的管理

本文参考