图解HTTP

杨旭 bio photo By 杨旭

Hypertext Transfer Protocol


  • HTTP协议是什么?

  • 为什么要学习HTTP协议?

  • HTTP协议包含哪些东西?

为什么要学习HTTP协议?

HTTP协议是Web技术的基础,理解HTTP协议能够*帮助我们快速理解各种技术原理*,同时能够帮助我们*解决日常工作中的各种问题*

帮助我们快速理解各种Web技术

近些年Web技术快速发展,但是究其根本,始终围绕着大量的基础概念和理论,HTTP协议便是其中重要的基础支柱之一。

深刻的理解HTTP协议的概念、主要内容,能够让我们以不变应万变,快速理解各种技术的背景、原理和解决方式。

例如:HTTP2.0究竟是什么?DNS是如何找到真实服务器的?RESTFUL接口应该如何定义?如何管理Web应用的缓存?

帮助我们解决日常工作中的问题

在日常工作中,我们面对各种稀奇古怪的需求和问题时,如果没有一定的理论支撑,通常会茫然不知所措或者难以找到解决方案。

了解协议本身的基本能力、交互过程、控制手段等等,能够帮助我们快速的分析和解决问题

例如:为何页面加载如此缓慢?修改的文件为何没有生效?服务器返回的302是什么意思?怎么提高网站的安全性?

HTTP协议是什么?

想要理解一项技术是什么,最好的方式是搞清楚:它的出现背景是什么解决了什么问题它是如何工作的会怎么演进

HTTP协议的出现背景是什么?

1989年,随着计算机网络技术的发展,学术界希望希望能够借助网络来共享和传输文档

大家希望能够通过同一的语言进行沟通和传输,于是出现了在传输层TCP/IP协议之上的应用层协议:HTTP协议

HTTP协议解决了什么问题?

  • HTTP协议用于客户端和服务器之间的通信 - 在HTTP协议中始终存在客户端和服务端的概念,两者是可以互换的

  • 通过请求和响应的交换达成通信 - 每个请求总是从客户端发起,由服务端响应,请求和响应中包含控制信息、状态和内容。

  • 通过统一资源标识符指定资源

  • 通过无状态设计保证可伸缩性 - 服务器不会记录请求过程,每个请求都是独立的,以此来保证协议的可伸缩性。

  • 通过语义化动词告知服务器请求的意图

  • 通过持久连接节省流量 - TCP协议的频繁握手会导致流量的浪费,HTTP/1.0通过keep-alive头建立持久连接,以此减轻服务器负担和提高传输效率。在HTTP/1.1中,默认采用长连接。

  • 使用Cookie保存身份信息 - 由服务器生成cookie并返回给客户端,此后客户端每次请求中都携带cookie信息,以此帮助服务端识别客户端身份。

与HTTP协议相关的概念有哪些?

  • TCP/IP 协议 - 互联网相关网络协议的合集,用来进行网络节点之间的通信协商、控制管理以及数据传输。

  • 负责传输的IP协议 - 位于网络层,用来把各种数据报传输给对方,通过IP地址和MAC地址来指定传输目标。

  • 用来查询MAC地址的ARP协议 - 基于IP地址反查出目标的MAC地址

  • 确保可靠性的TCP协议 - 位于传输层,提供可靠的字节流服务。为了支撑大数据量的分组传输,使用三次握手机制保证数据最终被正确送达。

  • 负责域名解析的DNS服务 - 位于应用层,提供域名到IP地址之间的映射服务。提供给用户容易记忆的域名地址,通过向DNS服务器及进行查询,后去实际可以访问的IP地址。

  • 统一资源标识符URI - 由某个协议方案表示的资源的定位标识符,例如:https://user:pass@www.example.com:80/dir/index.html?uid=1#ch1,当中包含了网络协议、认证信息、服务器地址、端口、文件路径、查询参数和片段标识符

  • 统一资源定位符URL - 访问Web页面时需要输入的地址

HTTP协议是如何工作的?

其他问题

  • TCP/IP协议为什么要分层?每一层都保持专注和独立发展,可以独立的进行优化和替换,相互间通过标准接口进行交互,减少各个分层之间的依赖关系。

  • URI和URL有什么区别?

  • 无状态性是如何保证伸缩性的?无状态保证各个服务请求之间没有依赖和关联,使水平伸缩才有可能实施。请求信息可以随时通过负载均衡技术分发到分布式集群中的任意节点上。

HTTP报文

用户HTTP协议交互的信息被成为HTTP报文

报文的结构

报文分为:

  • 首部:包括请求行/状态行、请求/响应首部字段、通用首部字段、实体首部字段
  • 空行:分隔首部和报文主体
  • 报文主体:请求或响应时的有效载荷数据

在传输过程中,报文主体的传输有以下基础支持:

  • 压缩传输:减少请求传输的数据大小,但是会增加两端的计算资源消耗
  • 分组传输:将大数据分隔为多块,让你更浏览器能够逐步显示
  • 多媒体传输:采用MINE支持图片、视频、文本等多种形式的数据传输
  • 部分请求:可以指定下载部分,提供可恢复机制
  • 内容协商:使用Accept-*等请求头来协商响应资源的语言、字符集、编码等

返回结果的HTTP状态码

用来表示服务端处理HTTP请求的结果。

  • HTTP response status codes

  • 1XX 信息性状态码:接收的请求正在处理
  • 2XX 成功状态码:请求正常处理完成
  • 3XX 重定向状态码:需要附加操作完成请求
  • 4XX 客户端错误状态码:服务器无法处理请求
  • 5XX 服务端错误状态码:服务器处理请求出错

其中常用的14种状态码

  • 200 OK 请求被服务器正确处理了
  • 204 No Content 请求被服务器正确处理了,但是不包含任何响应实体
  • 206 Partial Content 客户端进行了范围请求,响应中包含这部分响应

  • 301 Moved Permanently 永久性重定向,表示资源被永久性分配了新的URI
  • 302 Found 临时性重定向,表示资源只是临时被分配了新的URI
  • 303 See Other 临时性重定向,于302的区别是明确采用GET方法获取资源
  • 304 Not Modified 告知客户端内容未失效,可以直接使用缓存内容
  • 307 Temporary Redirect 于302类似,但是明确要求客户端不能将POST请求变为GET

  • 400 Bad Request 请求报文中存在语法错误
  • 401 Unauthorized 请求需要有HTTP认证的认证信息
  • 403 Forbidden 表示请求被服务器拒绝
  • 404 Not Found 服务器上无法找到请求的资源

  • 503 Service Unavailable 服务器可能处在超负载或停机维护状态,无法处理客户端请求

与HTTP协作的Web服务器

  • 代理:带有转发功能的应用程序,可以提供缓存或透明代理功能
  • 网管:转发与其他服务器通信的服务器,可以在内部使用非HTTP协议
  • 隧道:通信线路,目的是确保通信的安全性

HTTP首部

客户端与服务端通信时,最重要的控制功能都在报文首部

请求报文首部包括:

  • 请求行:方法、URI和协议版本
  • 请求首部字段:补充请求的附加信息、客户端内容、响应内容优先级等
  • 通用首部字段:请求和响应都会用到的字段
  • 实体首部字段:补充资源内容更新时间等与实体有关的信息

响应报文首部包括:

  • 状态行:协议版本、状态码
  • 响应首部字段:补充响应的附加信息,也会要求客户端附加额外内容
  • 通用首部字段:请求和响应都会用到的字段
  • 实体首部字段:补充资源内容更新时间等与实体有关的信息

通用首部字段

Cache-Control 操作缓存的工作机制

指令可以包含多个参数,使用“,”分隔

Cache-Control: private, max-age=0, no-cache

  • public和private 限制缓存的有效范围,所有用户都可以访问或只有特定用户可以使用
  • no-cache 强制要求到服务器验证缓存有效性,禁止缓存服务器对资源进行缓存
  • no-store 不进行缓存,包括缓存服务器和客户端
  • max-age 当存在于客户端请求时,用于校验缓存时长是否小于该值;当存在于服务器响应时,表示缓存保存的最大时长。HTTP1.1中max-age优先级高于Expires,1.0中则相反
  • max-stale 允许使用指定时间范围内的过期缓存
  • min-fresh 使用指定事件内还保持有效的缓存
  • only-if-cached 只使用缓存资源,如果失败则返回504 Gateway Timeout
  • must-revalidate 要求代理向源服务器再次确认缓存是否有效
  • no-transform 禁止缓存或代理压缩图片等操作

Connection

  • 控制不再转发给代理的首部字段
Connection: 不再转发的首部字段名
  • 管理持久连接:Keep-Alive保持连接,Close断开连接

Date 记录报文创建的时间

Transfer-Encoding 指定传输报文主体时的编码

Upgrade 升级到其他协议

Via 追踪客户端和服务器之间的传输路径

请求首部字段

  • Accept 使用type/subtype指定用户代理能处理的媒体类型和相对优先级
  • Accept-Charset 用户代理能够支持的字符集和相对优先级
  • Accept-Encoding 用户代理支持的内容编码和相对优先级
  • Accept-Language 用户代理能够支持的语言和相对优先级
  • Authorization 携带客户端的认证信息
  • Except 用户代理告知服务器,期望出现的某种特定行为
  • From 告知服务器用户代理的用户邮件地址
  • Host 指定实际服务器在虚拟主机中的名称和端口号,是1.1版本唯一指定必须包含的字段

以IF开头的请求字段都可以看作条件请求:

  • If-Match 当资源的e-tag匹配时才返回响应
  • If-Modified-Since 缓存的重要控制字段,服务器根据时间进行校验,如果在指定时间之后发生了更新,则返回新资源;如果没有更新,则返回304,客户端使用缓存。
  • If-None-Match 缓存的控制字段,当新资源的ETag与客户端的不匹配时,返回新资源
  • If-Range 如果字段指与ETag或时间一致,则作为范围请求处理,否则返回全体资源
  • If-Unmodified-Since 作用与If-Modified-Since相反

其他字段:

  • Max-Forwards 限制中转服务器最大数目,每次经过一个中转服务器,字段数量减1,到达0的时候停止转发
  • Range 告知服务器获取资源的范围
  • Referer 告知服务器请求的原始URI
  • TE 告知服务器,客户端能够处理响应的传输编码以及相对优先级,与Accept-Encoding类似,但是用于指定传输编码
  • User-Agent 用于传达客户端浏览器的种类

响应首部字段

  • Accept-Ranges 用来告知客户端,所请求的范围是否合理。分为bytes和none两个值。
  • Age 告知客户端,资源是源服务器在多少秒之前创建的
  • ETag 资源的唯一标志,没有统一算法,由服务器分配
    • 强Tag 资源的细微改变均发生变化
    • 弱Tag 资源发生根本改变时才变化,需要加上W/前缀
  • Location 配合3xx状态码,表明资源被转移,要求客户端重定向
  • Retry-After 配合503或者3xx进行返回,告知客户端在多少秒之后或者指定时间再来访问
  • Server 告知客户端,服务器的应用程序信息,可能包括版本号、启动选项等详细信息
  • Vary 指定一个header字段,经过代理服务器的时候,只有指定字段的值相同才使用缓存

实体首部字段

  • Allow 通知客户端能够获取资源的HTTP方法
  • Content-Encoding 告知客户端能够支持的压缩方式
  • Content-Language 告知客户端自然语言类型
  • Content-Length 表明主体长度,如果启用了压缩,则不能使用该字段
  • Content-Location 指明返回信息的实际URI
  • Content-MD5 内容的md5值,用于判断返回信息的正确性
  • Content-Range 返回当前部分以及整体的实体大小
  • Content-Type 返回信息的媒体类型
  • Expires 资源的失效日期,采用绝对时间,优先级低于max-age
  • Last-Modified 返回资源的最后修改时间

Cookie相关

  • Set-Cookie 响应首部字段
  • Cookie 请求首部字段

字段的属性:

  • NAME=VALUE 设置cookie的名称和值
  • expires=DATE 设置cookie的有效期,如果不设置,只保留在回话范围内;可以通过expires=0来删除cookie
  • path=PATH 将服务器上的文件目录作为Cookie的使用对象
  • domain=域名 指定使用对象的域名,默认是创建cookie的服务器的域名
  • Secure 仅在HTTPS安全通信时才会发送
  • HttpOnly 限制cookie不能被js访问,方式xss攻击篡改cookie

确保Web安全的HTTPS协议

HTTP协议的安全缺陷

  • 明文传输,可能导致信息被窃听
  • 不校验身份,可能出现伪装
  • 不校验完整性,可能导致被篡改

HTTP + 加密 + 认证 + 完整性保护 = HTTPS

HTTPS协议是披着SSL外壳的HTTP,HTTP与SSL协议交互,而SSL协议再与TCP协议进行交互。

加密

  • TCP/IP是可以被窃听的网络,使用常见的抓包工具即可看到请求的详细信息
  • 基于SSL协议,通信双方建立安全的通信通道,并且对传输内容进行加密/解密处理
  • 对称加密:通信双方使用相同的密钥,但是分发密钥的过程可能被攻击者拦截,一旦密钥泄漏则加密毫无意义
  • 非对称加密:加密和解密使用不同的密钥,使用公钥加密,使用私钥解密
  • 因为非对称加密更消耗性能,HTTPS协议使用混合模式,使用非对称加密交换密钥,使用对称加密传输信息
  • 为了确保公钥的正确性,需要借助权威的证书认证机构;运营人员将证书提交到认证机构,机构在认证、签名之后进行分发;客户端可以根据签名到认证机构进行校验,以确保公钥的可靠性。

用户身份的认证

常见的验证方式

  • 密码:只有本人才知道的字符串信息
  • 动态令牌:仅限本人持有的设备内显示的一次性密码
  • 数字证书:仅限本人(终端)持有的信息
  • 生物证书:指纹和虹膜等生理信息
  • IC卡:仅限本人持有的信息

在HTTP协议中的认证方式:

  • BASIC认证(基本认证)
  • DIGEST认证(摘要认证)
  • SSL客户端认证
  • FormBase认证(表单认证)

BASIC认证

原始的认证方式:

  • 服务器响应返回401,要求客户端提供用户名和密码信息
  • 客户端讲用户名和密码进行Base64编码后,在请求头中发送给服务器
  • 服务器认证通过后返回资源

但是这种方式并非真正的加密,一旦被窃听,危险性很高

DIGEST认证

与BASIC认证类似,采用质询/响应模式进行认证,但是不会发送明文的密码。

  • 服务端在401响应中携带随机生成的质询码
  • 客户端结合用户认证信息,计算响应码和摘要信息发送给服务端
  • 服务器收到响应码后,对用户信息进行认证

SSL客户端认证

  • 事先将客户端证书分发给客户端,并要求客户端安装证书
  • 当客户端请求时,要求客户端提供证书信息
  • 服务器认证通过后,才会建立安全的通信

表单认证

客户端要求输入用户名密码进行身份认证,通常与SSL客户端认证形成双因素认证

  • SSL认证客户端的计算机
  • 表单认证验证用户本人身份

HTTP的功能追加协议

SPDY

由于HTTP协议本身的限制,在使用时存在以下缺陷:

  • 一次连接只能发送一条请求
  • 请求只能从客户端开始,无法从服务端推送
  • 请求和响应的首部没有进行压缩处理
  • 首部信息冗长而且存在大量重复
  • 内容压缩是可选的

SPDY协议在HTTP协议和SSL协议之间增加了会话层,并且实现了如下功能:

  • 多路复用,每个连接可以发送多个请求
  • 首部压缩,减少每次请求的大小
  • 服务端推送
  • 服务端提示,提前告知客户端资源信息,避免多余请求

由于SPDY协议的部署需要客户端和服务器的支持,导致其应用效果不佳

WebSocket

在服务端和客户端之间建立全双工的通信

客户端在请求时通过Upgrade字段建立WebSocket连接,服务端通过101响应进行连接建立。建立连接后脱离HTTP协议,使用独立的桢进行数据传输。

因为采用独立的协议,可以避免HTTP协议本身的限制:

  • 服务端和客户端之间可以任意的传输信息
  • 删除了冗余的请求头