前端篇:网络基础之HTTP协议
前言
笔者通过《图解HTTP》一书系统的学习了HTTP协议的基础内容,将试图用更加简洁的方式描述出HTTP协议的内容,此篇在前端网络基础常见面试题基础上进行延伸,文中沿用的部分图片来自《图解HTTP》一书。
目录
1 HTTP报文
1.1 请求方法
1.2 状态码
1.3 报文首部
2 HTTPS
2.1 HTTP的缺点
2.2 HTTP+加密+认证+完整性保护=HTTPS
2.3 HTTPS 的安全通信机制
3 确认访问用户身份的认证
3.1 BASIC认证(基本认证)
3.2 DIGEST 认证(摘要认证)
3.3 SSL客户端认证
正文
1 HTTP报文
1.1 请求方法
- GET:获取资源
GET方法用来请求访问已被URI识别的资源。指定的资源经服务器端解析后返回响应的内容。
请求 | GET /index.html HTTP/1.1 |
响应 | 返回index.html的页面内容 |
- POST:传输实体主体
请求 | POST /submit.cgi HTTP/1.1 Host:www.hackr.jp Content-Length:1560(1560字节的数据) |
响应 | 返回submit.cgi接收数据的处理结果 |
- PUT:传输文件
请求 | PUT /example.html HTTP/1.1 Host:www.hackr.jp Content-Type:text/html Content-Length:1560(1560字节的数据) |
响应 | 响应返回状态码204 No Content(比如:该html已经存在于服务器上) |
- HEAD:获得报文首部
HEAD方法和GET方法一样,只是不返回报文主体部分。用于确认URI的有效性及资源更新的日期时间等。
请求 | HEAD /index.html HTTP/1.1 Host:www.hackr.jp |
响应 | 返回index.html有关的响应首部 |
- DELETE:删除文件
请求 | HEAD /index.html HTTP/1.1 Host:www.hackr.jp |
响应 | 响应返回状态码204 No Content(比如:该html已经从服务器上删除) |
- OPTIONS:询问支持的方式
请求 | OPTIONS * HTTP/1.1 |
响应 | HTTP/1.1 200 OK Allow:GET,POST,HEAD,OPTIONS (返回服务器支持的方法) |
- TRACE:追踪路径
- CONNECT:要求用隧道协议连接代理
HTTP/1.0 和 HTTP/1.1 支持的方法
LINK 和 UNLINK 已被 HTTP/1.1 废弃, 不再支持。
1.2 状态码
- 状态码类别
状态码 | 类别 | 原因短语 |
1XX | Informational(信息性状态码) | 接收的请求正在处理 |
2XX | Success(成功状态码) | 请求正常处理完毕 |
3XX | Redirection(重定向状态码) | 需要进行附加操作以完成操作 |
4XX | Client Error(客户端错误状态码) | 服务器无法处理请求 |
5XX | Server Error(服务器错误状态码) | 服务器处理请求出错 |
- 2XX 成功
(1)200:OK
表示从客户端发来的请求在服务器端被正常处理了。
在响应报文内,随状态码一起返回的信息会因方法的不同而发生改变。比如,使用 GET 方法时,对应请求资源的实体会作为响应返回;而使用 HEAD 方法时,对应请求资源的实体首部不随报文主体作为响应返回(即在响应中只返回首部,不会返回实体的主体部分)。
在响应报文内,随状态码一起返回的信息会因方法的不同而发生改变。比如,使用 GET 方法时,对应请求资源的实体会作为响应返回;而使用 HEAD 方法时,对应请求资源的实体首部不随报文主体作为响应返回(即在响应中只返回首部,不会返回实体的主体部分)。
(2)204:No Content
该状态码代表服务器接收的请求已成功处理,但在返回的响应报文中 不含实体的主体部分。
(3)206:Partial Content
该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的 GET 请求。响应报文中包含由 Content-Range 指定范围的实体内容。
- 3XX 重定向
永久性重定向。该状态码表示请求的资源已被分配了新的 URI,以后 应使用资源现在所指的 URI。也就是说,如果已经把资源对应的 URI 保存为书签了,这时应该按 Location 首部字段提示的 URI 重新保存。
像下方给出的请求 URI,当指定资源路径的最后忘记添加斜杠“/”,就会产生 301 状态码。
(2)302 Found
临时性重定向。该状态码表示请求的资源已被分配了新的 URI,希望 用户(本次)能使用新的 URI 访问。
和 301 Moved Permanently 状态码相似,但 302 状态码代表的资源不 是被永久移动,只是临时性质的。换句话说,已移动的资源对应的 URI 将来还有可能发生改变。比如,用户把 URI 保存成书签,但不会 像 301 状态码出现时那样去更新书签,而是仍旧保留返回 302 状态码 的页面对应的 URI。
(3)304 Not Modified
该状态码表示客户端发送附带条件的请求时,服务器端允许请求访问资源,但未满足条件的情况后,直接返回304 。304 状态码返回时,不包含任何响应的主体部分。304 虽然被划分在 3XX 类别中,但是和重定向没有关系。
- 4XX 客户端错误
该状态码表示请求报文中存在语法错误。当错误发生时,需修改请求 的内容后再次发送请求。另外,浏览器会像 200 OK 一样对待该状态码。
(2)404 Not Found
该状态码表明服务器上无法找到请求的资源。除此之外,也可以在服 务器端拒绝请求且不想说明理由时使用。
- 5XX 服务器错误
该状态码表明服务器端在执行请求时发生了错误。也有可能是 Web 应用存在的 bug 或某些临时的故障。
1.3 报文首部
HTTP报文结构
HTTP请求报文
在请求中,HTTP 报文由方法、URI、HTTP 版本、HTTP 首部字段等部分构成。
下面的示例是访问 http://hackr.jp 时,请求报文的首部信息。
HTTP 响应报文
在响应中,HTTP 报文由 HTTP 版本、状态码(数字和原因短语)、 HTTP 首部字段 3 部分构成。
以下示例是之前请求访问 http://hackr.jp/ 时,返回的响应报文的首部信息。
HTTP/1.1 首部字段
- 这里结合表格和思维导图方便大家记忆
- 注意:思维导图是某些首部字段名的细分,不代表它就是常见的字段名,这里是为让大家更多地了解其他字段。
通用首部字段
首部字段名 | 说明 |
Cache-Control | 控制缓存的行为 |
Connection | 逐跳首部、连接的管理 |
Date | 创建报文的日期时间 |
Pragma | 报文指令 |
Trailer | 报文末端的首部一览 |
Transfer-Encoding | 指定报文主体的传输编码方式 |
Upgrade | 升级为其他协议 |
Via | 代理服务器的相关信息 |
Warning | 错误通知 |
Cache-Control
- 缓存请求指令
- 缓存响应指令
Connection
Pragma
Trailer
Via
请求首部字段名
首部字段名 | 说明 |
Accept | 用户代理可处理的媒体类型 |
Accept-Charset | 优先的字符集 |
Accept-Encoding | 告知服务器用户代理支持的内容编码及内容编码的优先级顺序。 |
Accept-Language | 优先的语言(自然语言) |
Authorization | Web认证信息 |
Expect | 期待服务器的特定行为 |
From | 用户的电子邮箱地址 |
Host | 请求资源所在服务器 |
If-Match | 比较实体标记(Etag) |
If-Modified-Since | 比较资源更新时间 |
If-None-Match | 比较实体标记(与If-Match相反) |
If-Range | 资源未更新时发送实体Byte的范围请求 |
If-Unmodefied-Since | 比较资源的更新时间(与If-Modified-Since相反) |
Max-Forwards | 最大传输逐跳数 |
Proxy-Authorization | 代理服务器要求客户端的认证信息 |
Range | 实体的字节范围请求 |
Referer | 对请求中的URI的原始获取方 |
TE | 传输编码的优先级 |
User-Agent | HTTP客户端程序的信息(创建请求的浏览器和用户代理名称等信息) |
Accept
Accept-Encoding
Authorization
If-Match
If-Modified-Since
If-Range
TE
响应首部字段
首部字段名 | 说明 |
Accept-Ranges | 是否接受字节范围请求 |
Age | 推算资源创建经过时间 |
ETag | 资源的匹配信息 |
Location | 令客户端重定向至指定URI |
Proxy-Authenticate | 代理服务器对客户端的认证信息 |
Retry-After | 对再次发起请求的时机要求 |
Server | HTTP服务器的安装信息 |
Vary | 代理服务器缓存的管理信息 |
WWW-Authenticate | 服务器对客户端的认证信息 |
Accept-Ranges
ETag
Retry-After
实体首部字段
首部字段名 | 说明 |
Allow | 资源可支持的HTTP方法 |
Content-Encoding | 实体主体适用的编码方式 |
Content-Language | 实体主体的自然语言 |
Content-Length | 实体主体的大小(单位:字节) |
Content-Location | 代替对应资源的URI |
Content-MD5 | 实体主体的报文摘要 |
Content-Range | 实体主体的位置范围 |
Content-Type | 实体主体的媒体类型 |
Expires | 实体主体过期的日期时间 |
Last-Modified | 资源的最后修改日期时间 |
Content-Encoding
Content-MD5
2 HTTPS
2.1 HTTP的缺点
- 通信使用明文(不加密),内容可能会被窃听
- 不验证通信方的身份,因此有可能遭遇伪装
- 无法证明报文的完整性,所以有可能已遭篡改
2.2 HTTP+加密+认证+完整性保护=HTTPS
- HTTPS 采用混合加密机制
遗憾的是,公开密钥加密方式还是存在一些问题的。那就是无法证明公开密钥本身就是货真价实的公开密钥。为了解决上述问题,可以使用由数字证书认证机构(CA)和其相关机关颁发的公开密钥证书。
数字证书认证机构的业务流程
首先,服务器的运营人员向数字证书认证机构提出公开密钥的申请。数字证书认证机构在判明提出申请者的身份之后,会对已申请的公开密钥做数字签名,然后分配这个已签名的公开密钥,并将该公开密钥放入公钥证书后绑定在一起。服务器会将这份由数字证书认证机构颁发的公钥证书发送给客户端,以进行公开密钥加密方式通信。公钥证书也可叫做数字证书或直接称为证书。接到证书的客户端可使用数字证书认证机构的公开密钥,对那张证书上的数字签名进行验证,一旦验证通过,客户端便可明确两件事: 一是认证服务器的公开密钥的是真实有效的数字证书认证机构。二是服务器的公开密钥是值得信赖的。
HTTPS 中还可以使用客户端证书。以客户端证书进行客户端认证,证明服务器正在通信的对方始终是预料之内的客户端,其作用跟服务器证书如出一辙。
2.3 HTTPS 的安全通信机制
步骤 1: 客户端通过发送 Client Hello 报文开始 SSL通信。报文中包含客户端支持的SSL的指定版本、加密组件(Cipher Suite)列表(所使用的加密算法及密钥长度等)。
步骤 2: 服务器可进行 SSL通信时,会以 Server Hello 报文作为应答。和客户端一样,在报文中包含 SSL版本以及加密组件。服务器的加密组件内容是从接收到的客户端加密组件内筛选出来的。
步骤 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 报文。上图做了一些省略,这步之后再发送 TCP FIN 报文来关闭与 TCP 的通信。
下面是对整个流程的图解。图中说明了从仅使用服务器端的公开密钥 证书(服务器证书)建立 HTTPS 通信的整个过程。
3 确认访问用户身份的认证
3.1 BASIC认证(基本认证)
- 认证步骤
步骤 1: 当请求的资源需要 BASIC 认证时,服务器会随状态码 401 Authorization Required,返回带 WWW-Authenticate 首部字段的响应。 该字段内包含认证的方式(BASIC) 及 Request-URI 安全域字符串 (realm)。
步骤 2: 接收到状态码 401 的客户端为了通过 BASIC 认证,需要将用户 ID 及密码发送给服务器。发送的字符串内容是由用户 ID 和密码构成,两者中间以冒号(:)连接后,再经过 Base64 编码处理。 假设用户 ID 为 guest,密码是 guest,连接起来就会形成 guest:guest 这样的字符串。然后经过 Base64 编码,最后的结果即是 Z3Vlc3Q6Z3Vlc3Q=。把这串字符串写入首部字段 Authorization 后, 发送请求。 当用户代理为浏览器时,用户仅需输入用户 ID 和密码即可,之后, 浏览器会自动完成到 Base64 编码的转换工作。
步骤 3: 接收到包含首部字段 Authorization 请求的服务器,会对认证 信息的正确性进行验证。如验证通过,则返回一条包含 Request-URI 资源的响应。
3.2 DIGEST 认证(摘要认证)
- 认证步骤
步骤 1: 请求需认证的资源时,服务器会随着状态码 401 Authorization Required,返 回带 WWW-Authenticate 首部字段的响应。 该字段内包含质问响应方式认证所需的临时质询码(随机数, nonce)。
- 首部字段 WWW-Authenticate 内必须包含 realm 和 nonce 这两个字段的 信息。客户端就是依靠向服务器回送这两个值进行认证的。
- nonce 是一种每次随返回的 401 响应生成的任意随机字符串。该字符 串通常推荐由 Base64 编码的十六进制数的组成形式,但实际内容依 赖服务器的具体实现。
- 首部字段 Authorization 内必须包含 username、realm、nonce、uri 和 response 的字段信息。其中,realm 和 nonce 就是之前从服务器接收到 的响应中的字段。
- username 是 realm 限定范围内可进行认证的用户名。
- uri(digest-uri)即 Request-URI 的值,但考虑到经代理转发后 Request-URI 的值可能被修改,因此事先会复制一份副本保存在 uri 内。
- response 也可叫做 Request-Digest,存放经过 MD5 运算后的密码字符串,形成响应码。
3.3 SSL客户端认证
- 认证步骤
步骤 2: 用户选择将发送的客户端证书后,客户端会把客户端证书信 息以 Client Certificate 报文方式发送给服务器。
步骤 3: 服务器验证客户端证书验证通过后方可领取证书内客户端的公开密钥,然后开始 HTTPS 加密通信。