《图解HTTP》读书笔记

Author Avatar
jiandandkl 9月 30, 2018
本文总阅读量
  • 在其它设备中阅读本文章

书读了一遍发现没记住什么,团队过面试题时聊到401和403的区别,只是模糊有点印象但说不上来,就考虑做个读书笔记吧,加深下印象。
原书名《今晚我们一起学习http》相比《图解HTTP》更有日本特色。

一、TCP/IP协议

分为应用层 / 传输层 / 网络层 / 链路层。

  • 应用层
    决定了向用户提供应用服务时通信的活动,包含FTP/DNS服务及HTTP协议。

  • 传输层
    提供处于网络连接中计算机之间的数据传输,有TCP(传输控制协议)和UDP(用户数据报协议)。

  • 网络层
    处理网络上流动的数据包,该层规定了通过怎样的路径到达对方计算机,并把数据包传给对方。与对方计算机之间通过多台计算机或网络设备进行传输时,网络层的作用就是在众多的选项内选择一条传输路线。

  • 链路层
    用来处理连接网络的硬件部分。

通信过程
  1. 在应用层(HTTP协议)发出一个http请求
  2. 为了传输方便,在传输层(TCP协议)把从应用层收到的数据(HTTP请求报文)进行分割,并在各个报文打上标记序号及端口号转发给网络层
  3. 在网络层(IP协议)增加作为通信目的地的MAC地址后转发给链路层
IP / TCP / DNS
  • IP
  1. IP协议的作用就是把各种数据包传送给对方
  2. IP地址指明了节点被分配到的地址,MAC地址是指网卡所属的固定地址
  3. ARP协议是一种用以解析地址的协议,根据通信放的IP地址可以反查出对应的MAC地址
  • TCP
  1. 提供字节流服务: 将大块数据分割成报文段为单位的数据包进行管理。
  2. 为准确将数据送达目标处,采用三次握手策略: 发送端先发送一个带SYN标志的数据包给对方。接收端收到后,回传一个带有SYN/ACK标志的数据包以示传达确认信息。最后发送端再回传一个带有ACK标志的数据包,代表握手结束。
  • DNS
  1. 和HTTP协议一样位于应用层的协议,提供域名到IP地址的解析服务,或逆向从IP地址反查域名

二、HTTP协议

HTTP是无状态协议,为了实现保持状态功能,引入Cookie技术

HTTP支持的方法

GET/POST/PUT/HEAD/DELETE/OPTIONS/TRACE/CONNECT

持久连接

只要任意一端没有明确提出断开连接,则保持TCP连接。
减少了TCP连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载;减少开销的时间,使HTTP请求和响应更早结束,页面显示速度也提高了。

管线化

可以并行发送多个请求

三、HTTP报文内的HTTP信息

报文主体与实体主体

HTTP 在传输数据时可以按照数据原貌直接传输,但也可以在传输 过程中通过编码提升传输速率。
通常,报文主体等于实体主体。只有当传输中进行编码操作时,实体主体的内容发生变化,才导致它和报文主体产生差异。

获取部分内容的范围请求

从之前下载中断处恢复下载的功能。使用首部字段: Range,如:
Range: bytes=5001-10000
Range: bytes=-3000, 5000-7000

针对范围请求,响应会返回状态码为 206 Partial Content 的响应报文。另外,对于多重范围的范围请求,响应会在首部字段 Content-Type 标明 multipart/byteranges 后返回响应报文。
如果服务器端无法响应范围请求,则会返回状态码 200 OK 和完整 的实体内容。

四、HTTP状态码

类别 原因短语
1XX Informational(信息性状态码) 接收的请求正在处理
2XX Success(成功状态码) 请求正常处理完毕
3XX Redirection(重定向状态码) 需要进行附加操作以完成请求
4XX Client Error(客户端错误状态码) 服务器无法处理请求
5XX Server Error(服务器错误状态码) 服务器处理请求出错
常见状态码
状态码 code 介绍 场景
204 No Content 已成功处理,但响应报文中不含实体的主体部分 一般在只需要从客户端往服务器发送信息,而对客户端不需要发送 056 新信息内容的情况下使用
206 Partial Content 成功执行范围请求
301 Moved Permanently 永久性重定向 如果已经把资源对应的 URI 保存为书签了,这时应该按 Location 首部字段提示的 URI 重新保存
302 Found 临时性重定向 该状态码表示请求的资源已被分配了新的 URI,希 望用户(本次)能使用新的URI访问(会转到响应报文首部的Location字段的地址)
304 Not Modified 该状态码表示客户端发送附带条件的请求时,服务器端允许请求访问资源,但请求未满足条件,不包含任何响应的主体部分
400 Bad Request 请求报文中存在语法错误
401 Unauthorized 发送的请求需要有通过 HTTP 认证的认证信息
403 Forbidden 对请求资源的访问被服务器拒绝了 未获得文件系统的访问授权,访问权限出现某些问题(从未授权的 发送源 IP 地址试图访问)
404 Not Found 服务器上无法找到请求的资源或服务器端拒绝请求且不想说明理由时
500 Internal Server Error 服务器端在执行请求时发生了错误
503 Service Unavailable 服务器暂时处于超负载或正在进行停机维护,无法处理请求

五、与HTTP协作的web服务器

通信数据转发程序:代理、网关、隧道
  • 代理

    • 一种有转发功能的应用程序
    • 可级联多台代理服务器, 每经过一台需要附加Via首部字段以标记出经过的主机信息
    • 优点: 利用缓存技术减少网络带宽的流量,组织内部针对特定网站的访问控制,以获取访问日志为主要目的
  • 网关

    • 是转发其他服务器通信数据的服务器,接收从客户端发送来的 请求时,它就像自己拥有资源的源服务器一样对请求进行处理。有 时客户端可能都不会察觉,自己的通信目标是一个网关
    • 利用网关能提高通信的安全性,因为可以在客户端与网关之间的通信线路上加密以确保连接的安全
  • 隧道

    • 是在相隔甚远的客户端和服务器两者之间进行中转,并保持双方通信连接的应用程序
    • 目的是确保客户端能与服务器进行安全的通信

六、HTTP首部

HTTP请求报文

由方法、URI、HTTP版本、HTTP首部字段等部分构成

HTTP响应报文

由 HTTP 版本、状态码、HTTP首部字段3部分构成

HTTP首部字段

分为以下4种类型(常用举例):

类型首部字段名说明
通用首部字段Cache-Control控制缓存的行为
Connection逐跳首部、连接的管理
Pragma报文指令
请求首部字段Accept用户代理可处理的媒体类型
Accept-Charset优先的字符集
Accept-Encoding优先的内容编码
AuthorizationWeb认证信息
AuthorizationWeb认证信息
Referer对请求中URI的原始获取方
响应首部字段Accept-Ranges是否接受字节范围请求
Location令客户端重定向至指定URI
Age推算资源创建经过时间
实体首部字段Allow资源可支持的 HTTP 方法
Content-Encoding实体主体适用的编码方式
Content-Length实体主体的大小(单位:字节)
HTTP/1.1 通用首部字段
  • Cache-Control
指令 说明
public 其他用户也可利用缓存
private 响应只以特定的用户作为对象
no-cache 不缓存过期的资源
no-store 真·不进行缓存
must-revalidate 代理会向源服务器再次证即将返回的响应缓存目前是否仍然有效

同时存在max-age和Expires时,HTTP/1.1会优先处理max-age,忽略Expries,HTTP/1.0相反

  • Connection
  • 控制不再转发给代理
    Connection: 不再转发的首部字段
    如: Connection: Upgrade, 代理服务器就会把首部字段中的Upgrade删掉

  • 管理持久连接
    Connection: close
    HTTP/1.1默认连接都是持久连接,当服务器端想明确断开连接可设置close
    HTTP/1.1之前都是非持久连接,若想维持持续连接,可设置Keep-Alive

  • Date
    创建 HTTP 报文的日期和时间

  • Pragma
    Pragma 是 HTTP/1.1 之前版本的历史遗留字段,仅作为与 HTTP/1.0 的向后兼容而定义
    所以发送请求会同时含有以下两个首部字段:

      Cache-Control: no-cache
      Pragma: no-cache
  • Trailer
    会事先说明在报文主体后记录了哪些首部字段。该首部字段可应用在 HTTP/1.1 版本分块传输编码时

  • Transfer-Encoding
    规定了传输报文主体时采用的编码方式。
    HTTP/1.1 的传输编码方式仅对分块传输编码有效

  • Upgrade
    检测是否可使用更高的版本进行通信,可以是完全不同的通信协议

  • Via
    Via 是为了追踪客户端与服务器之间的请求和响应报文的传输路径
    报文经过代理或网关时,会先在首部字段 Via附中该加该服务器的信息,然后再进行转发

请求首部字段
  • Accept

    通知服务器用户代理能够处理的媒体类型及优先级, type/subtype是一次指定多种媒体类型
    文本文件: text/html, text/plain, text/css
    图片文件: image/jpeg, image/gif
    视频文件: video/mpeg

    使用q=来表示权重值,q的范围是0~1,服务器会首先返回权重值高的媒体类型

  • Accept-Charset
    支持的字符集及字符集的优先顺序,同样用q表示优先级
    Accept-Charset: iso-8859-5, unicode-1-1;q=0.8

  • Accept-Encoding
    支持的内容编码及优先级顺序,使用星号*作为通配符,为任意编码格式,同样用q表示优先级
    如gzip

  • Authorization
    用来告知服务器,用户代理的认证信息。通常想要通过服务器认证的用户代理会在接收到返回的401状态码后,把首部字段Authorization加入请求中。

  • From
    告知服务器使用用户代理的用户的电子邮件地址。
    目的是为了显示搜索引擎等用户代理的负责人的电子邮件联系方式。(因代理不同,可能在User-Agent首部字段内)

  • If-xxx
    形如If-xxx的请求首部字段,都是条件请求,服务器接收到附带条件的请求后,只有判断条件为真时才会执行请求

    • If-match会告知服务器匹配资源所用的实体标记(ETag)值,若匹配不到返回412Precondition Failed的响应

    • If-Modified-Since用于确认代理或客户端拥有的本地资源的有效性,若没有更新过,返回304Not Modified 的响应

    • If-Range若是ETag值或更新的日期时间匹配一致就作为范围请求处理;若不一致,则忽略范围请求,返回全部资源
      如果不用If-Range,仅用Range范围请求,若没有资源,服务器会返回412Precondition Failed,目的是催促客户端再次发生请求,与If-Range相比就花费了两倍的功夫。

  • Max-Forwards
    指定可经过服务器的最大数目,在往下一个服务转发请求之前会将字段值减1后重新赋值。可以避免经过多台服务器转发请求失败,客户端得不到响应的问题;以及当字段值为-时,服务器会立即返回响应,对这条服务器为终点的传输路径的通信状况有所把握

  • Range
    只需获取部分资源的范围请求,服务器后处理请求后返回206Partial Content 的响应,若无法处理,则返回200 OK及全部资源

  • Referer
    告知服务器请求的原始资源的URI,服务器能知道从哪个web页面发起的。

    Referer的正确拼写应该是Referrer,一人提出时拼写错误写入了HTTP/1.0协议,后来发现已经大量使用了,就将错就错一直保留了。详情可见

响应首部字段
  • Accept-Ranges 是用来告知客户端服务器是否能处理范围请求,可处理时为bytes,反之为none

  • Age 告知客户端源服务器在多久前创建了响应,单位为秒

  • ETag 是一种将资源以字符串形式做唯一标识的方式。

    • 强ETag值,不论实体发生多么细微的变化都会改变其值
    • 弱ETag值,只用于提示资源是否相同,只有发送根本改变才会改变ETag值,这时在开头加W/,如: ETag: W/"usagi-1234"
  • Location 可以将响应接收方引导至某个与请求 URI 位置不同的资源, 一般配合3xx的响应,提供重定向的URI

  • Proxy-Authenticate 会把由代理服务器所要求的认证信息发送给客户端

  • Retry-After 告知客户端应该在多久之后再次发送请求,值可以是具体的日期时间或创建响应后的秒数

  • Server 告知客户端当前服务器上安装的 HTTP 服务器应用程序的信息

  • Vary 可对缓存进行控制, 仅对请求中含有相同Vary指定首部字段的请求返回缓存

  • WWW-Authenticate 用于HTTP访问认证,它会告知客户端适用于 问请求 URI 所指定资源的认证方案(Basic 或是 Digest)和 数提示的质询(challenge)。

实体首部字段
  • Content-Location 表示的是报文主体返回资源对应的 URI
  • Content-MD5 是一串由 MD5算法生成的值,其目的在于检查报文主体在传输过程中是否保持完整,以及确认传输到达。
  • Expires 资源失效的日期
  • Last-Modified 资源最终修改的时间
其他首部字段
  • X-Frame-Options
    属于 HTTP 响应首部,用于控制网站内容在其他 Web 网站的 Frame 标签内的显示问题。其主要目的是为了防止点击劫持(click acking)攻击

    • DENY: 拒绝
    • SAMEORIGIN:仅同源域名下的页面匹配时许可
  • X-XSS-Protection
    属于 HTTP 响应首部,它是针对跨站脚本攻击(XSS)的一种对策,用于控制浏览器XSS防护机制的开关

    • 0: 将XSS过滤设置成无效状态
    • 1: 将XSS过滤设置成有效状态
  • DNT
    属于HTTP请求首部,Do Not Track,意为拒绝个人信息被收集,是表示拒绝被精准广告追踪的一种方法

    • 0: 同意被追踪
    • 1: 拒绝被追踪

七、确保Web安全的HTTPS

HTTP加上加密处理和认证以及完整性保护后即是HTTPS

  • HTTP的缺点
  • 通信使用明文(不加密) 内容可能会被窃听
  • 不验证通信方的身份,因此有可能遭遇伪装
  • 无法证明报文的完整性,所以有可能已遭篡改

HTTPS并非新协议,只是HTTP通信接口部分用SSL和TLS协议代替了。

  • 相互交换密钥的公开密钥加密技术

公开密钥加密使用一对非对称的密钥,一把是私有密钥,一把是公开密钥。
发送密文的一方使用对方的公开密钥进行加密,对方收到加密的信息后,使用自己的私有密钥进行解密。使用这种方式,不需要发送用来解密的私有密钥,也不必担心密钥被攻击者窃听而盗走。

  • HTTPS采用混合加密机制
    公开密钥加密与共享密钥加密相比,处理速度要慢;
    具体表现为:
    • 和HTTP相比网络负载可能会慢2到100倍,除去和TCP连接、发送HTTP请求,还必须进行SSL通信,因此整体上处理通信量会增加
    • 服务器和客户端都需要进行加密和解密的运算处理,会更多地消耗服务器和客户端的硬件资源,导致负载增强

      没有根本性的解决方案,可以使用SSL加速器(专用服务器)硬件来改善该问题
      在交换密钥环境使用公开密钥加密方式,之后的建立通信交换报文阶段使用共享密钥加密方式

HTTPS的安全通信机制
  1. 客户端通过发送Client Hello报文开始SSL通信。报文中包含客户端支持的 SSL 的指定版本、加密组件(Cipher Suite)列表(所使用的加密算法及密钥长度等)
  2. 服务器可进行SSL通信时,会以Server Hello报文作为应答。
  3. 之后服务器发送Certificate报文。报文中包含公开密钥证书。
  4. 最后服务器发送Server Hello Done报文通知客户端,最初阶段的 SSL 握手协商部分结束。
  5. SSL 第一次握手结束之后,客户端以Client Key Exchange 报文作为回应。报文中包含通信加密中使用的一种被称为 Pre-master secret的随机密码串。该报文已用步骤3中的公开密钥进行加密。
  6. 接着客户端继续发送Change Cipher Spec报文。该报文会提示服务器,在此报文之后的通信会采用 Pre-master secret 密钥加密。
  7. 客户端发送 Finished 报文。该报文包含连接至今全部报文的整体校验值。这次握手协商是否能够成功,要以服务器是否能够正确解密该报文作为判定标准。
  8. 服务器同样发送 Change Cipher Spec 报文。
  9. 服务器同样发送Finished报文。
  10. 服务器和客户端的 Finished 报文交换完毕之后,SSL连接就 建立完成。当然,通信会受到 SSL 的保护。从此处开始进行应用层协议的通信,即发送 HTTP 请求
  11. 应用层协议通信,即发送 HTTP 响应。
  12. 最后由客户端断开连接。断开连接时,发送 close notify报文

在以上流程中,应用层发送数据时会附加一种叫做 MAC(Message Authentication Code)的报文摘要。MAC 能够查知报文是否遭到 改, 从而保护报文的完整 。

八、确认访问用户身份的认证

  • BASIC认证

    1. 当请求的资源需要BASIC认证,服务器会响应401
    2. 客户端将用户id及密码Base64编码后发给服务器(无加密)
    3. 通过认证,服务器返回包含资源的响应

      既无加密,也无法实现认证注销的操作

  • DIGEST认证

    1. 类似BASIC认证,响应401,包含临时质询码(随机数,noce)
    2. 返回经过MD5运算后的密码字符串等
    3. 通过认证返回包含资源的响应,并在首部字段 Authentication-Info 写入一些认证成功的相关信息

      虽然提供防止密码被窃听的保护机制,但并不存在防止用户伪装的保护机制。

  • SSL客户端认证

    • 认证步骤

      1. 接收到请求,服务器会发生Certificate Request 报文,要求客户端提供客户端证书
      2. 客户端会把客户端证书信息以 Client Certificate 报文方式发送给服务器
      3. 服务器验证客户端证书验证通过后方可领取证书内客户端的 开密钥,然后开始 HTTPS 加密通信
    • 双因素认证
      一般和基于表单认证组合形成双因素认证来使用,第一个SSL客户端证书用来认证客户端计算机,另一个认证因素的密码则用来确定是用户本人

  • 基于表单认证

九、基于HTTP的功能追加协议

  • HTTP存在的问题

    • 一条连接上只可发送一个请求
    • 请求只能从客户端开始
    • 请求/响应首部未经压缩就发送,首部嘻嘻越多延迟越大
    • 每次互相发送相同的/冗长的首部造成浪费
    • 可任意选择数据压缩格式,非强制压缩
  • Ajax的解决方法
    只更新一部分页面,响应中传输的数据量也因此减少。但有可能导致大量请求产生。

  • Comet的解决方法
    一旦服务器有内容更新了,Comet会直接给客户端返回响应。但为了保留响应,一次连接的持续时间也变长了,为了维持连接也会消耗更多的资源。

  • SPDY的解决方法(已被HTTP/2替代)
    SPDY以会话层的形式加入,控制对数据的流动,但还是采用HTTP建立通信连接。
    使用SPDY后,HTTP协议额外获得以下功能:

    • 多路复用流:
      通过单一的TCP连接,可以无限制处理多个HTTP请求。所有请求的处理都在一条TCP连接上,因此TCP的处理效率得到提高。
    • 赋予请求优先级
    • 压缩HTTP首部
    • 推送功能
    • 服务器提示功能
全双工通信的WebSocket

主要是解决Ajax和Comet里XMLHTTPRequest附带的缺陷所引起的问题;
建立在HTTP基础上的协议,连接的发起方仍是客户端,而一旦确立WebSocket通信连接,不论服务器还是客户端,任意一方都可以直接向对方发送报文。

  • 推送功能
    支持由服务器向客户端推送数据的推送功能

  • 减少通信量
    只要建立起WebSocket连接,就希望一直保持连接状态,而且Websocket首部信息很小,通信量也减少了

为了实现WebSocket通信,在HTTP连接建立后需要完成一次握手的步骤

  • 握手请求
    设置Upgrade为webSocket,Sec-WebSocket-Key字段内记录着握手过程中必不可少的键值,Sec-WebSocket-Protocol 字段内记录使用的子协议

  • 握手响应
    返回状态码 101 Switching Protocols

成功握手确立 WebSocket连接之后,通信时不再使用 HTTP 的数据帧,而 采用 WebSocket 独立的数据帧

  • WebSocket API
    每 50ms 发送一次数据的实例:

     var socket = new WebSocket('ws://game.example.com:12010/updates'); socket.onopen = function () {
      setInterval(function() {
        if (socket.bufferedAmount == 0)
          socket.send(getUpdateData());
      }, 50);
    };
  • HTTP/2
    目标是改善用户在使用Web时的速度体验,基于SPDY

    • 帧、消息、流和TCP连接
      将一个TCP连接分为若干个流(Stream),每个流中可以传输若干消息(Message),每个消息由若干最小的二进制帧(Frame)组成
    • HPACK 算法
      用于对HTTP头部做压缩
    • 服务器推送
      服务端向客户端发送比客户端请求更多的数据。这允许服务器直接提供浏览器渲染页面所需资源,而无须浏览器在收到、解析页面后再提起一轮请求,节约了加载时间