HTTP基本概念
1.HTTP **是什么?**能否详细解释
HTTP 是超⽂本传输协议,也就是HyperText Transfer Protocol。
HTTP 是⼀个在计算机世界⾥专⻔在「两点」之间「传输」⽂字、图⽚、⾳频、视频等「超⽂本」数据的**「约定和规范」。**
2.「HTTP 是⽤于从互联⽹服务器传输超⽂本到本地浏览器的协议」,这种说法正确吗?
这种说法是不正确的。因为也可以是「服务器< – >服务器」,所以采⽤两点之间的描述会更准确。
3.HTTP 常⻅的状态码有哪些?
![image-20240810221526067](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fraw.githubusercontent.com%2Fdaichang01%2Fpic-bed%2Fmain%2Fimage-20240810221526067.png&pos_id=img-mcZfUTlm-1723361175162%29)
1xx 类状态码属于提示信息,是协议处理中的⼀种中间状态,实际⽤到的⽐较少。
2xx 类状态码表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。「200 OK」是最常⻅的成功状态码,表示⼀切正常。如果是⾮ HEAD 请求,服务器返回的响应头
都会有 body 数据。
「204 No Content」也是常⻅的成功状态码,与 200 OK 基本相同,但响应头没有 body 数据。
「206 Partial Content」是应⽤于 HTTP 分块下载或断点续传,表示响应返回的 body 数据并不是资
源的全部,⽽是其中的⼀部分,也是服务器处理成功的状态。
3xx 类状态码表示客户端请求的资源发⽣了变动,需要客户端⽤新的 URL ᯿新发送请求获取资源,也就
是重定向。
「301 Moved Permanently」表示永久᯿定向,说明请求的资源已经不存在了,需改⽤新的 URL 再
次访问。
「302 Found」表示临时᯿定向,说明请求的资源还在,但暂时需要⽤另⼀个 URL 来访问。
301 和 302 都会在响应头⾥使⽤字段 Location ,指明后续要跳转的 URL,浏览器会⾃动᯿定向新的
URL。
「304 Not Modified」不具有跳转的含义,表示资源未修改,᯿定向已存在的缓冲⽂件,也称缓存᯿
定向,也就是告诉客户端可以继续使⽤缓存资源,⽤于缓存控制。
4xx 类状态码表示客户端发送的报⽂有误,服务器⽆法处理,也就是错误码的含义。
「400 Bad Request」表示客户端请求的报⽂有错误,但只是个笼统的错误。
「403 Forbidden」表示服务器禁⽌访问资源,并不是客户端的请求出错。
「404 Not Found」表示请求的资源在服务器上不存在或未找到,所以⽆法提供给客户端。
5xx 类状态码表示客户端请求报⽂正确,但是服务器处理时内部发⽣了错误,属于服务器端的错误码。
「500 Internal Server Error」与 400 类型,是个笼统通⽤的错误码,服务器发⽣了什么错误,我们
并不知道。
「501 Not Implemented」表示客户端请求的功能还不⽀持,类似“即将开业,敬请期待”的意思。
「502 Bad Gateway」通常是服务器作为⽹关或代理时返回的错误码,表示服务器⾃身⼯作正常,访
问后端服务器发⽣了错误。
「503 Service Unavailable」表示服务器当前很忙,暂时⽆法响应客户端,类似“⽹络服务正忙,请
稍后᯿试”的意思。
4.HTTP 常⻅字段有哪些?
- Host 字段
客户端发送请求时,⽤来指定服务器的域名。有了 Host 字段,就可以将请求发往「同⼀台」服务器上的不同⽹站。
Host: www.A.com
- Content-Length 字段
服务器在返回数据时,会有 Content-Length 字段,表明本次回应的数据⻓度
![image-20240810221920404](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fraw.githubusercontent.com%2Fdaichang01%2Fpic-bed%2Fmain%2Fimage-20240810221920404.png&pos_id=img-pyxbzhWZ-1723361175936%29)
Content-Length: 1000
HTTP 是基于 TCP 传输协议进⾏通信的,⽽使⽤了 TCP 传输协议,就会存在⼀个“粘包”
的问题,HTTP 协议通过设置回⻋符、换⾏符作为 HTTP header 的边界,通过 Content-Length 字段作
为 HTTP body 的边界,这两个⽅式都是为了解决**“粘包”**的问题。
- Connection 字段
Connection 字段最常⽤于客户端要求服务器使⽤「HTTP ⻓连接」机制,以便其他请求复⽤。
![image-20240810222041335](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fraw.githubusercontent.com%2Fdaichang01%2Fpic-bed%2Fmain%2Fimage-20240810222041335.png&pos_id=img-q0CyV17M-1723361176159%29)
HTTP ⻓连接的特点是,只要任意⼀端没有明确提出断开连接,则保持 TCP 连接状态。
![image-20240810222146312](https://img-blog.csdnimg.cn/img_convert/2da94207eeb64faba2f7b1b9bbb308c4.png)
HTTP/1.1 版本的默认连接都是⻓连接,但为了兼容⽼版本的 HTTP,需要指定 Connection ⾸部字段的
值为 Keep-Alive 。
开启了 HTTP Keep-Alive 机制后, 连接就不会中断,⽽是保持连接。当客户端发送另⼀个请求时,它会使
⽤同⼀个连接,⼀直持续到客户端或服务器端提出断开连接
- Content-Type 字段
Content-Type 字段⽤于服务器回应时,告诉客户端,本次数据是什么格式。
![image-20240810222259668](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fraw.githubusercontent.com%2Fdaichang01%2Fpic-bed%2Fmain%2Fimage-20240810222259668.png&pos_id=img-adA0vVhE-1723361177473%29)
Content-Type: text/html; Charset=utf-8
上⾯的类型表明,发送的是⽹⻚,⽽且编码是UTF-8。
客户端请求的时候,可以使⽤ Accept 字段声明⾃⼰可以接受哪些数据格式。
Accept: /
上⾯代码中,客户端声明⾃⼰可以接受任何格式的数据
- Content-Encoding 字段
Content-Encoding 字段说明数据的压缩⽅法。表示服务器返回的数据使⽤了什么压缩格式
![image-20240810222358780](https://img-blog.csdnimg.cn/img_convert/f21b20b3e17afb53bfa96c4230c3de62.png)
Content-Encoding: gzip
上⾯表示服务器返回的数据采⽤了 gzip ⽅式压缩,告知客户端需要⽤此⽅式解压。
客户端在请求时,⽤ Accept-Encoding 字段说明⾃⼰可以接受哪些压缩⽅法。
Accept-Encoding: gzip, deflate
GET与POST
5. GET 和 POST 有什么区别?
GET 的语义是从服务器获取指定的资源,这个资源可以是静态的⽂本、⻚⾯、图⽚视频
等。GET 请求的参数位置⼀般是写在 URL 中,URL 规定只能⽀持 ASCII,所以 GET 请求的参数只允许
ASCII 字符 ,⽽且浏览器会对 URL 的⻓度有限制(HTTP协议本身对 URL⻓度并没有做任何规定)。
POST 的语义是根据请求负荷(报⽂body)对指定的资源做出处理,具体的处理⽅式视
资源类型⽽不同。POST 请求携带数据的位置⼀般是写在报⽂ body 中,body 中的数据可以是任意格式的
数据,只要客户端与服务端协商好即可,⽽且浏览器不会对 body ⼤⼩做限制。
⽐如,你在我⽂章底部,敲⼊了留⾔后点击「提交」(暗示你们留⾔),浏览器就会执⾏⼀次 POST 请
求,把你的留⾔⽂字放进了报⽂ body ⾥,然后拼接好 POST 请求头,通过 TCP 协议发送给服务器。
6.GET 和 POST ⽅法都是安全和幂等的吗
先说明下安全和幂等的概念:
在 HTTP 协议⾥,所谓的「安全」是指请求⽅法不会「破坏」服务器上的资源。
所谓的「幂等」,意思是多次执⾏相同的操作,结果都是「相同」的。
- GET ⽅法就是安全且幂等的,因为它是「只读」操作,⽆论操作多少次,服务器上的数据都是安全
的,且每次的结果都是相同的。所以,可以对 GET 请求的数据做缓存,这个缓存可以做到浏览器本
身上(彻底避免浏览器发请求),也可以做到代理上(如nginx),⽽且在浏览器中 GET 请求可以保
存为书签。
- POST 因为是「新增或提交数据」的操作,会修改服务器上的资源,所以是不安全的,且多次提交数
据就会创建多个资源,所以不是幂等的。所以,浏览器⼀般不会缓存 POST 请求,也不能把 POST
请求保存为书签
如果「安全」放⼊概念是指信息是否会被泄漏的话,虽然 POST ⽤ body 传输数据,⽽ GET ⽤ URL 传
输,这样数据会在浏览器地址拦容易看到,但是并不能说 GET 不如 POST 安全的。
因为 HTTP 传输的内容都是明⽂的,虽然在浏览器地址拦看不到 POST 提交的 body 数据,但是只要抓个
包就都能看到了。
所以,**要避免传输过程中数据被窃取,就要使⽤ HTTPS 协议,**这样所有 HTTP 的数据都会被加密传输。
7.GET 请求可以带 body 吗?
RFC 规范并没有规定 GET 请求不能带 body 的。理论上,任何请求都可以带 body 的。只是因为 RFC 规
范定义的 GET 请求是获取资源,所以根据这个语义不需要⽤到 body。
另外,URL 中的查询参数也不是 GET 所独有的,POST 请求的 URL 中也可以有参数的。
HTTP缓存技术
8.HTTP 缓存有哪些实现⽅式?
对于⼀些具有᯿复性的 HTTP 请求,⽐如每次请求得到的数据都⼀样的,我们可以把这对「请求-响应」的
数据都缓存在本地,那么下次就直接读取本地的数据,不必在通过⽹络获取服务器的响应了,这样的话
HTTP/1.1 的性能肯定⾁眼可⻅的提升。
所以,避免发送 HTTP 请求的⽅法就是通过缓存技术,HTTP 设计者早在之前就考虑到了这点,因此 HTTP
协议的头部有不少是针对缓存的字段。
HTTP 缓存有两种实现⽅式,分别是强制缓存和协商缓存。
9.什么是强制缓存?
强缓存指的是只要浏览器判断缓存没有过期,则直接使⽤浏览器的本地缓存,决定是否使⽤缓存的主动性
在于浏览器这边。
如下图中,返回的是 200 状态码,但在 size 项中标识的是 from disk cache,就是使⽤了强制缓存
![image-20240810231554705](https://img-blog.csdnimg.cn/img_convert/2de6a53e648f5c7855877029abe193b8.png)
强缓存是利⽤下⾯这两个 HTTP 响应头部(Response Header)字段实现的,它们都⽤来表示资源在客户
端缓存的有效期:
Cache-Control , 是⼀个相对时间;
Expires ,是⼀个绝对时间;
如果 HTTP 响应头部同时有 Cache-Control 和 Expires 字段的话,Cache-Control 的优先级⾼于 Expires
。
Cache-control 选项更多⼀些,设置更加精细,所以建议使⽤ Cache-Control 来实现强缓存。具体的实现
流程如下:
-
当浏览器第⼀次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上Cache-Control,Cache-Control 中设置了过期时间⼤⼩;
-
浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与 Cache-Control 中设置的过
期时间⼤⼩,来计算出该资源是否过期,如果没有,则使⽤该缓存,否则᯿新请求服务器;
- 服务器再次收到请求后,会再次更新 Response 头部的 Cache-Control
10.什么是协商缓存?
当我们在浏览器使⽤开发者⼯具的时候,你可能会看到过某些请求的响应码是 304 ,这个是告诉浏览器
可以使⽤本地缓存的资源,通常这种通过服务端告知客户端是否可以使⽤缓存的⽅式被称为协商缓存。
![image-20240810231817558](https://img-blog.csdnimg.cn/img_convert/93e5cdff46b0b4485c630cb95e3267f7.png)
上图就是⼀个协商缓存的过程,所以协商缓存就是与服务端协商之后,通过协商结果来判断是否使⽤本地
缓存。
协商缓存可以基于两种头部来实现。
第⼀种:请求头部中的 If-Modified-Since 字段与响应头部中的 Last-Modified 字段实现,这两个字段
的意思是
-
响应头部中的 Last-Modified :标示这个响应资源的最后修改时间;
-
请求头部中的 If-Modified-Since :当资源过期了,发现响应头中具有 Last-Modified 声明,则再次
发起请求的时候带上 Last-Modified 的时间,服务器收到请求后发现有 If-Modified-Since 则与被请求
资源的最后修改时间进⾏对⽐(Last-Modified),如果最后修改时间较新(⼤),说明资源⼜被改
过,则返回最新资源,HTTP 200 OK;如果最后修改时间较旧(⼩),说明资源⽆新修改,响应
HTTP 304 ⾛缓存。
第⼆种:请求头部中的 If-None-Match 字段与响应头部中的 ETag 字段,这两个字段的意思是:
-
响应头部中 Etag :唯⼀标识响应资源;
-
请求头部中的 If-None-Match :当资源过期时,浏览器发现响应头⾥有 Etag,则再次向服务器发起
请求时,会将请求头 If-None-Match 值设置为 Etag 的值。服务器收到请求后进⾏⽐对,如果资源没
有变化返回 304,如果资源变化了返回 200。
第⼀种实现⽅式是基于时间实现的,第⼆种实现⽅式是基于⼀个唯⼀标识实现的,相对来说后者可以更加
准确地判断⽂件内容是否被修改,避免由于时间篡改导致的不可靠问题。
如果在第⼀次请求资源的时候,服务端返回的 HTTP 响应头部同时有 Etag 和 Last-Modified 字段,那么客
户端再下⼀次请求的时候,如果带上了 ETag 和 Last-Modified 字段信息给服务端,这时 Etag 的优先级更
⾼,也就是服务端先会判断 Etag 是否变化了,如果 Etag 有变化就不⽤在判断 Last-Modified 了,如果
Etag 没有变化,然后再看 Last-Modified。
为什么 ETag **的优先级更⾼?**这是因为 ETag 主要能解决 Last-Modified ⼏个⽐较难以解决的问题:
- 在没有修改⽂件内容情况下⽂件的最后修改时间可能也会改变,这会导致客户端认为这⽂件被改动
了,从⽽᯿新请求;
- 可能有些⽂件是在秒级以内修改的, If-Modified-Since 能检查到的粒度是秒级的,使⽤ Etag就能够
保证这种需求下客户端在 1 秒内能刷新多次;
- 有些服务器不能精确获取⽂件的最后修改时间。
注意,协商缓存这两个字段都需要配合强制缓存中 Cache-Control 字段来使⽤,只有在未能命中强制缓存
的时候,才能发起带有协商缓存字段的请求。
下图是强制缓存和协商缓存的⼯作流程:
![image-20240810232333791](https://img-blog.csdnimg.cn/img_convert/88dc5a830d4459da83a48ca4674b37f5.png)
当使⽤ ETag 字段实现的协商缓存的过程:
-
当浏览器第⼀次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上ETag 唯⼀标识,这个唯⼀标识的值是根据当前请求的资源⽣成的;
-
当浏览器再次请求访问服务器中的该资源时,⾸先会先检查强制缓存是否过期:
如果没有过期,则直接使⽤本地缓存;
如果缓存过期了,会在 Request 头部加上 If-None-Match 字段,该字段的值就是 ETag 唯⼀标识;
- 服务器再次收到请求后,会根据请求中的 If-None-Match 值与当前请求的资源⽣成的唯⼀标识进⾏
⽐较:
如果值相等,则返回 304 Not Modified**,不会返回资源**;
如果不相等,则返回 200 状态码和返回资源,并在 Response 头部加上新的 ETag 唯⼀标识;
如果浏览器收到 304 的请求响应状态码,则会从本地缓存中加载资源,否则更新资源。
HTTP特性
到⽬前为⽌,HTTP 常⻅到版本有 HTTP/1.1,HTTP/2.0,HTTP/3.0,不同版本的 HTTP 特性是不⼀样的。
11.HTTP/1.1 的优点有哪些?
1. 简单
HTTP 基本的报⽂格式就是 header + body ,头部信息也是 key-value 简单⽂本的形式,易于理解,降
低了学习和使⽤的⻔槛。
2. 灵活和易于扩展
HTTP 协议⾥的各类请求⽅法、URI/URL、状态码、头字段等每个组成要求都没有被固定死,都允许开发
⼈员⾃定义和扩充。
同时 HTTP 由于是⼯作在应⽤层( OSI 第七层),则它下层可以随意变化,⽐如:
HTTPS 就是在 HTTP 与 TCP 层之间增加了 SSL/TLS 安全传输层;
HTTP/1.1 和 HTTP/2.0 传输协议使⽤的是 TCP 协议,⽽到了 HTTP/3.0 传输协议改⽤了 UDP 协议。
3. 应⽤⼴泛和跨平台
互联⽹发展⾄今,HTTP 的应⽤范围⾮常的⼴泛,从台式机的浏览器到⼿机上的各种 APP,从看新闻、刷
贴吧到购物、理财、吃鸡,HTTP 的应⽤遍地开花,同时天然具有跨平台的优越性。
12.HTTP/1.1 的缺点有哪些?
HTTP 协议⾥有优缺点⼀体的双刃剑,分别是「⽆状态、明⽂传输」,同时还有⼀⼤缺点「不安全」。
1. ⽆状态双刃剑
⽆状态的好处,因为服务器不会去记忆 HTTP 的状态,所以不需要额外的资源来记录状态信息,这能减轻
服务器的负担,能够把更多的 CPU 和内存⽤来对外提供服务。
⽆状态的坏处,既然服务器没有记忆能⼒,它在完成有关联性的操作时会⾮常麻烦。
⽆状态的好处,因为服务器不会去记忆 HTTP 的状态,所以不需要额外的资源来记录状态信息,这能减轻
服务器的负担,能够把更多的 CPU 和内存⽤来对外提供服务。
⽆状态的坏处,既然服务器没有记忆能⼒,它在完成有关联性的操作时会⾮常麻烦。例如登录->添加购物⻋->下单->结算->⽀付,这系列操作都要知道⽤户的身份才⾏。但服务器不知道这些
请求是有关联的,每次都要问⼀遍身份信息。
这样每操作⼀次,都要验证信息,这样的购物体验还能愉快吗?别问,问就是酸爽!
对于⽆状态的问题,解法⽅案有很多种,其中⽐较简单的⽅式⽤ Cookie 技术。
Cookie 通过在请求和响应报⽂中写⼊ Cookie 信息来控制客户端的状态。
相当于,在客户端第⼀次请求后,服务器会下发⼀个装有客户信息的「⼩贴纸」,后续客户端请求服务器
的时候,带上「⼩贴纸」,服务器就能认得了了,
2. 明⽂传输双刃剑
明⽂意味着在传输过程中的信息,是可⽅便阅读的,⽐如 Wireshark 抓包都可以直接⾁眼查看,为我们调
试⼯作带了极⼤的便利性。
但是这正是这样,HTTP 的所有信息都暴露在了光天化⽇下,相当于信息裸奔。在传输的漫⻓的过程中,
信息的内容都毫⽆隐私可⾔,很容易就能被窃取,如果⾥⾯有你的账号密码信息,那你号没了。
3. 不安全
HTTP ⽐较严᯿的缺点就是不安全:
-
通信使⽤明⽂(不加密),内容可能会被窃听。⽐如,账号信息容易泄漏,那你号没了。
-
不验证通信⽅的身份,因此有可能遭遇伪装。⽐如,访问假的淘宝、拼多多,那你钱没了。
-
⽆法证明报⽂的完整性,所以有可能已遭篡改。⽐如,⽹⻚上植⼊垃圾⼴告,视觉污染,眼没了。
HTTP 的安全问题,可以⽤ HTTPS 的⽅式解决,也就是通过引⼊ SSL/TLS 层,使得在安全上达到了极致。
13.HTTP/1.1 的性能如何?
HTTP 协议是基于 TCP/IP,并且使⽤了「请求 - 应答」的通信模式,所以性能的关键就在这两点⾥。
1. ⻓连接
早期 HTTP/1.0 性能上的⼀个很⼤的问题,那就是每发起⼀个请求,都要新建⼀次 TCP 连接(三次握
⼿),⽽且是串⾏请求,做了⽆谓的 TCP 连接建⽴和断开,增加了通信开销。
为了解决上述 TCP 连接问题,HTTP/1.1 提出了⻓连接的通信⽅式,也叫持久连接。这种⽅式的好处在于
减少了 TCP 连接的᯿复建⽴和断开所造成的额外开销,减轻了服务器端的负载。
持久连接的特点是,只要任意⼀端没有明确提出断开连接,则保持 TCP 连接状态。
当然,如果某个 HTTP ⻓连接超过⼀定时间没有任何数据交互,服务端就会主动断开这个连接。
2. 管道⽹络传输
HTTP/1.1 采⽤了⻓连接的⽅式,这使得管道(pipeline)⽹络传输成为了可能
即可在同⼀个 TCP 连接⾥⾯,客户端可以发起多个请求,只要第⼀个请求发出去了,不必等其回来,就可
以发第⼆个请求出去,可以减少整体的响应时间。
举例来说,客户端需要请求两个资源。以前的做法是,在同⼀个 TCP 连接⾥⾯,先发送 A 请求,然后等待服务器做出回应,收到后再发出 B 请求。那么,管道机制则是允许浏览器同时发出 A 请求和 B 请求,如下图:
但是服务器必须按照接收请求的顺序发送对这些管道化请求的响应。
如果服务端在处理 A 请求时耗时⽐较⻓,那么后续的请求的处理都会被阻塞住,这称为「队头堵塞」。
所以,HTTP/1.1 管道解决了请求的队头阻塞,但是没有解决响应的队头阻塞。
::: tip
注意**!!!**
实际上 HTTP/1.1 管道化技术不是默认开启,⽽且浏览器基本都没有⽀持,所以后⾯所有⽂章讨论
HTTP/1.1 都是建⽴在没有使⽤管道化的前提。⼤家知道有这个功能,但是没有被使⽤就⾏了。
3. 队头阻塞
「请求 - 应答」的模式会造成 HTTP 的性能问题。为什么呢?
因为当顺序发送的请求序列中的⼀个请求因为某种原因被阻塞时,在后⾯排队的所有请求也⼀同被阻塞
了,会招致客户端⼀直请求不到数据,这也就是「队头阻塞」,好⽐上班的路上塞⻋
总之 HTTP/1.1 的性能⼀般般,后续的 HTTP/2 和 HTTP/3 就是在优化 HTTP 的性能。
HTTP与HTTPS
14.HTTP 与 HTTPS 有哪些区别?
-
HTTP 是超⽂本传输协议,信息是明⽂传输,存在安全⻛险的问题。HTTPS 则解决 HTTP 不安全的缺陷,在 TCP 和 HTTP ⽹络层之间加⼊了 SSL/TLS 安全协议,使得报⽂能够加密传输。
-
HTTP 连接建⽴相对简单, TCP 三次握⼿之后便可进⾏ HTTP 的报⽂传输。⽽ HTTPS 在 TCP 三次握⼿之后,还需进⾏ SSL/TLS 的握⼿过程,才可进⼊加密报⽂传输。
-
两者的默认端⼝不⼀样,HTTP 默认端⼝号是 80,HTTPS 默认端⼝号是 443。
-
HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的
15.HTTPS 解决了 HTTP 的哪些问题?
HTTP 由于是明⽂传输,所以安全上存在以下三个⻛险:
窃听⻛险,⽐如通信链路上可以获取通信内容,⽤户号容易没。
篡改⻛险,⽐如强制植⼊垃圾⼴告,视觉污染,⽤户眼容易瞎。
冒充⻛险,⽐如冒充淘宝⽹站,⽤户钱容易没
![image-20240811090546781](https://img-blog.csdnimg.cn/img_convert/3ebf13d96c3421afbbc390f9b85e8bf3.png)
HTTPS 在 HTTP 与 TCP 层之间加⼊了 SSL/TLS 协议,可以很好的解决了上述的⻛险:
信息加密:交互信息⽆法被窃取,但你的号会因为「⾃身忘记」账号⽽没。
校验机制:⽆法篡改通信内容,篡改了就不能正常显示,但百度「竞价排名」依然可以搜索垃圾⼴
告。
身份证书:证明淘宝是真的淘宝⽹,但你的钱还是会因为「剁⼿」⽽没。
可⻅,只要⾃身不做「恶」,SSL/TLS 协议是能保证通信是安全的。
16.HTTPS 是如何解决上⾯的三个⻛险的?
-
混合加密的⽅式实现信息的机密性,解决了窃听的⻛险。
-
摘要算法的⽅式来实现完整性,它能够为数据⽣成独⼀⽆⼆的「指纹」,指纹⽤于校验数据的完整性,解决了篡改的⻛险。
-
将服务器公钥放⼊到数字证书中,解决了冒充的⻛险。
1. 混合加密通过混合加密的⽅式可以保证信息的机密性,解决了窃听的⻛险。
HTTPS 采⽤的是对称加密和⾮对称加密结合的「混合加密」⽅式:
-
在通信建⽴前采⽤⾮对称加密的⽅式交换「会话秘钥」,后续就不再使⽤⾮对称加密。
-
在通信过程中全部使⽤对称加密的「会话秘钥」的⽅式加密明⽂数据。
采⽤「混合加密」的⽅式的原因:
-
对称加密只使⽤⼀个密钥,运算速度快,密钥必须保密,⽆法做到安全的密钥交换。
-
⾮对称加密使⽤两个密钥:公钥和私钥,公钥可以任意分发⽽私钥保密,解决了密钥交换问题但速度慢。
2. 摘要算法 + 数字签名
为了保证传输的内容不被篡改,我们需要对内容计算出⼀个「指纹」,然后同内容⼀起传输给对⽅。对⽅收到后,先是对内容也计算出⼀个「指纹」,然后跟发送⽅发送的「指纹」做⼀个⽐较,如果「指纹」相同,说明内容没有被篡改,否则就可以判断出内容被篡改了。
那么,在计算机⾥会⽤摘要算法(哈希函数)来计算出内容的哈希值,也就是内容的「指纹」,这个哈希****值是唯⼀的,且⽆法通过哈希值推导出内容。
通过哈希算法可以确保内容不会被篡改,但是并不能保证「内容 + 哈希值」不会被中间⼈替换,因为这⾥****缺少对客户端收到的消息是否来源于服务端的证明。
那为了避免这种情况,计算机⾥会⽤⾮对称加密算法来解决,共有两个密钥:
-
⼀个是公钥,这个是可以公开给所有⼈的;
-
⼀个是私钥,这个必须由本⼈管理,不可泄露。
这两个密钥可以双向加解密的,⽐如可以⽤公钥加密内容,然后⽤私钥解密,也可以⽤私钥加密内容,公钥解密内容。
流程的不同,意味着⽬的也不相同:
- 公钥加密,私钥解密。这个⽬的是为了保证内容传输的安全,因为被公钥加密的内容,其他⼈是⽆法解密的,只有持有私钥的⼈,才能解密出实际的内容;
- 私钥加密,公钥解密。这个⽬的是为了保证消息不会被冒充,因为私钥是不可泄露的,如果公钥能正常解密出私钥加密的内容,就能证明这个消息是来源于持有私钥身份的⼈发送的。
⼀般我们不会⽤⾮对称加密来加密实际的传输内容,因为⾮对称加密的计算⽐较耗费性能的。
所以⾮对称加密的⽤途主要在于通过「私钥加密,公钥解密」的⽅式,来确认消息的身份,我们常说的数
字签名算法,就是⽤的是这种⽅式,不过私钥加密内容不是内容本身,⽽是对内容的哈希值加密。
![image-20240811092413948](https://img-blog.csdnimg.cn/img_convert/4a49b991e48c6ee81c30b18d1a1261d8.png)
私钥是由服务端保管,然后服务端会向客户端颁发对应的公钥。如果客户端收到的信息,能被公钥解密,就说明该消息是由服务器发送的。
引⼊了数字签名算法后,你就⽆法模仿你爸爸的字迹来请假了,你爸爸⼿上持有着私钥,你⽼师持有着公钥。
这样只有⽤你爸爸⼿上的私钥才对请假条进⾏「签名」,⽼师通过公钥看能不能解出这个「签名」,如果能解出并且确认内容的完整性,就能证明是由你爸爸发起的请假条,这样⽼师才允许你请假,否则⽼师就不认。
3. 数字证书
前⾯我们知道:
-
可以通过哈希算法来保证消息的完整性;
-
可以通过数字签名来保证消息的来源可靠性(能确认消息是由持有私钥的⼀⽅发送的);
但是这还远远不够,还缺少身份验证的环节,万⼀公钥是被伪造的呢?
在计算机⾥,这个权威的机构就是 CA (数字证书认证机构),将服务器公钥放在数字证书(由数字证书
认证机构颁发)中,只要证书是可信的,公钥就是可信的。
通过数字证书的⽅式保证服务器公钥的身份,解决冒充的⻛险。
17.HTTPS 是如何建⽴连接的?其间交互了什么?
SSL/TLS 协议基本流程:
-
客户端向服务器索要并验证服务器的公钥。
-
双⽅协商⽣产「会话秘钥」。
-
双⽅采⽤「会话秘钥」进⾏加密通信。
前两步也就是 SSL/TLS 的建⽴过程,也就是 TLS 握⼿阶段。
TLS 的「握⼿阶段」涉及四次通信,使⽤不同的密钥交换算法,TLS 握⼿流程也会不⼀样的,现在常⽤的密钥交换算法有两种:RSA 算法 和 ECDHE 算法。
基于 RSA 算法的 TLS 握⼿过程⽐较容易理解,所以这⾥先⽤这个给⼤家展示 TLS 握⼿过程,如下图:
![image-20240811094757915](https://img-blog.csdnimg.cn/img_convert/e6a376371086329630ba4c55afc649fd.png)
TLS 协议建⽴的详细流程:
1. ClientHello
⾸先,由客户端向服务器发起加密通信请求,也就是 ClientHello 请求。
在这⼀步,客户端主要向服务器发送以下信息:
(1)客户端⽀持的 TLS 协议版本,如 TLS 1.2 版本。
(2)客户端⽣产的随机数( Client Random ),后⾯⽤于⽣成「会话秘钥」条件之⼀。
(3)客户端⽀持的密码套件列表,如 RSA 加密算法。
2. SeverHello
服务器收到客户端请求后,向客户端发出响应,也就是 SeverHello 。服务器回应的内容有如下内容:
(1)确认 TLS 协议版本,如果浏览器不⽀持,则关闭加密通信。
(2)服务器⽣产的随机数( Server Random ),也是后⾯⽤于⽣产「会话秘钥」条件之⼀。
(3)确认的密码套件列表,如 RSA 加密算法。
(4)服务器的数字证书。
*3.*客户端回应
客户端收到服务器的回应之后,⾸先通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证书的真
实性。如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后使⽤它加密报⽂,向服务器发送如下
信息:
(1)⼀个随机数( pre-master key )。该随机数会被服务器公钥加密。
(2)加密通信算法改变通知,表示随后的信息都将⽤「会话秘钥」加密通信。
(3)客户端握⼿结束通知,表示客户端的握⼿阶段已经结束。这⼀项同时把之前所有内容的发⽣的数据做
个摘要,⽤来供服务端校验。
上⾯第⼀项的随机数是整个握⼿阶段的第三个随机数,会发给服务端,所以这个随机数客户端和服务端都
是⼀样的。
服务器和客户端有了这三个随机数(Client Random、Server Random、pre-master key),接着就⽤双
⽅协商的加密算法,各⾃⽣成本次通信的「会话秘钥」。
4. 服务器的最后回应
服务器收到客户端的第三个随机数( pre-master key )之后,通过协商的加密算法,计算出本次通信的
「会话秘钥」。
然后,向客户端发送最后的信息:
(1)加密通信算法改变通知,表示随后的信息都将⽤「会话秘钥」加密通信。
(2)服务器握⼿结束通知,表示服务器的握⼿阶段已经结束。这⼀项同时把之前所有内容的发⽣的数据做
个摘要,⽤来供客户端校验。
⾄此,整个 TLS 的握⼿阶段全部结束。接下来,客户端与服务器进⼊加密通信,就完全是使⽤普通的
HTTP 协议,只不过⽤「会话秘钥」加密内容。
::: tip
如果想深⼊学习基于 RSA 算法的 HTTPS 握⼿过程,可以看这篇,我通过抓包的⽅式,逐步分析每⼀个过
程:HTTPS RSA 握⼿解析
不过,基于 RSA 算法的 HTTPS 存在「前向安全」的问题:如果服务端的私钥泄漏了,过去被第三⽅截获
的所有 TLS 通讯密⽂都会被破解。
为了解决这个问题,后⾯就出现了 ECDHE 密钥协商算法,我们现在⼤多数⽹站使⽤的正是 ECDHE 密钥
协商算法,关于 ECDHE 握⼿的过程可以看这篇⽂章:HTTPS ECDHE 握⼿解析
:::
18.客户端校验数字证书的流程是怎样的?
如下图图所示,为数字证书签发和验证流程
![image-20240811095459796](https://img-blog.csdnimg.cn/img_convert/c9a26f361d5af492e87cd3648707ed3e.png)
CA 签发证书的过程,如上图左边部分:
- ⾸先 CA 会把持有者的公钥、⽤途、颁发者、有效时间等信息打成⼀个包,然后对这些信息进⾏
Hash 计算,得到⼀个 Hash 值;
- 然后 CA 会使⽤⾃⼰的私钥将该 Hash 值加密,⽣成 Certificate Signature,也就是 CA 对证书做了签
名;
- 最后将 Certificate Signature 添加在⽂件证书上,形成数字证书;
客户端校验服务端的数字证书的过程,如上图右边部分:
-
⾸先客户端会使⽤同样的 Hash 算法获取该证书的 Hash 值 H1;
-
通常浏览器和操作系统中集成了 CA 的公钥信息,浏览器收到证书后可以使⽤ CA 的公钥解密
Certificate Signature 内容,得到⼀个 Hash 值 H2 ;
- 最后⽐较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信
但事实上,证书的验证过程中还存在⼀个证书信任链的问题,因为我们向 CA 申请的证书⼀般不是根证书
签发的,⽽是由中间证书签发的,⽐如百度的证书,从下图你可以看到,证书的层级有三级
![image-20240811100404042](https://img-blog.csdnimg.cn/img_convert/ab7317d1745c585586ff13750d792a21.png)
![image-20240811100435235](https://img-blog.csdnimg.cn/img_convert/e3477d87af646c99e5e791369c15f58c.png)
19.为什么需要证书链这么麻烦的流程?Root CA 为什么不直接颁发证书,⽽是要搞那么多中间层级呢?
这是为了确保根证书的绝对安全性,将根证书隔离地越严格越好,不然根证书如果失守了,那么整个信任
链都会有问题。
20.HTTPS 的应⽤数据是如何保证完整性的?
TLS 在实现上分为握⼿协议和记录协议两层:
-
TLS 握⼿协议就是我们前⾯说的 TLS 四次握⼿的过程,负责协商加密算法和⽣成对称密钥,后续⽤此密钥来保护应⽤程序数据(即 HTTP 数据);
-
TLS 记录协议负责保护应⽤程序数据并验证其完整性和来源,所以对 HTTP 数据加密是使⽤记录协议;
TLS 记录协议主要负责消息(HTTP 数据)的压缩,加密及数据的认证,过程如下图:
具体过程如下:
-
首先,消息被分割成多个较短的片段,然后分别对每个片段进行压缩。
-
接下来,经过压缩的片段会被加上消息认证码(MAC 值,这个是通过哈希算法生成的),这是为了保证完整性,并进行数据的认证。通过附加消息认证码的 MAC 值,可以识别出篡改。与此同时,为了防止重放攻击,在计算消息认证码时,还加上了片段的编码。
-
再接下来,经过压缩的片段再加上消息认证码会一起通过对称密码进行加密。
-
最后,上述经过加密的数据再加上由数据类型、版本号、压缩后的长度组成的报头就是最终的报文数据。
记录协议完成后,最终的报文数据将传递到传输控制协议 (TCP) 层进行传输。
如果你想详细了解记录协议是如何分片、压缩、计算 MAC 值、分组加密,可以看这篇:理解 SSL/TLS 系列 (四) 记录协议
21.HTTPS ⼀定安全可靠吗?
这个问题的场景是这样的:客户端通过浏览器向服务端发起 HTTPS 请求时,被「假基站」转发到了一个「中间人服务器」,于是客户端是和「中间人服务器」完成了 TLS 握手,然后这个「中间人服务器」再与真正的服务端完成 TLS 握手。
![image-20240811143146123](https://img-blog.csdnimg.cn/img_convert/00ff631fff3f338210a7c49e9d8389b2.png)
从客户端的⻆度看,其实并不知道⽹络中存在中间⼈服务器这个⻆⾊。那么中间⼈就可以解开浏览器发起
的 HTTPS 请求⾥的数据,也可以解开服务端响应给浏览器的 HTTPS 响应数据。相当于,中间⼈能够 “偷
看” 浏览器与服务端之间的 HTTPS 请求和响应的数据。
但是要发⽣这种场景是有前提的,前提是⽤户点击接受了中间⼈服务器的证书。
中间⼈服务器与客户端在 TLS 握⼿过程中,实际上发送了⾃⼰伪造的证书给浏览器,⽽这个伪造的证书是
能被浏览器(客户端)识别出是⾮法的,于是就会提醒⽤户该证书存在问题。
如果⽤户执意点击「继续浏览此⽹站」,相当于⽤户接受了中间⼈伪造的证书,那么后续整个 HTTPS 通
信都能被中间⼈监听了。
所以,这其实并不能说 HTTPS 不够安全,毕竟浏览器都已经提示证书有问题了,如果⽤户坚决要访问,
那不能怪 HTTPS ,得怪⾃⼰⼿贱。
另外,如果你的电脑中毒了,被恶意导⼊了中间⼈的根证书,那么在验证中间⼈的证书的时候,由于你操
作系统信任了中间⼈的根证书,那么等同于中间⼈的证书是合法的,这种情况下,浏览器是不会弹出证书
存在问题的⻛险提醒的。
这其实也不关 HTTPS 的事情,是你电脑中毒了才导致 HTTPS 数据被中间⼈劫持的。
所以,HTTPS 协议本身到⽬前为⽌还是没有任何漏洞的,即使你成功进⾏中间⼈攻击,本质上是利⽤了客
户端的漏洞(⽤户点击继续访问或者被恶意导⼊伪造的根证书),并不是 HTTPS 不够安全。
22.为什么抓包⼯具能截取 HTTPS 数据?
很多抓包⼯具 之所以可以明⽂看到 HTTPS 数据,⼯作原理与中间⼈⼀致的。
对于 HTTPS 连接来说,中间⼈要满⾜以下两点,才能实现真正的明⽂代理:
- 中间⼈,作为客户端与真实服务端建⽴连接这⼀步不会有问题,因为服务端不会校验客户端的身份;
- 中间⼈,作为服务端与真实客户端建⽴连接,这⾥会有客户端信任服务端的问题,也就是服务端必须
有对应域名的私钥;
中间⼈要拿到私钥只能通过如下⽅式:
- 去⽹站服务端拿到私钥;
- 去CA处拿域名签发私钥;
- ⾃⼰签发证书,切要被浏览器信任;
不⽤解释,抓包⼯具只能使⽤第三种⽅式取得中间⼈的身份。
使⽤抓包⼯具进⾏ HTTPS 抓包的时候,需要在客户端安装 Fiddler 的根证书,这⾥实际上起认证中⼼
(CA)的作⽤。
抓包⼯具能够抓包的关键是客户端会往系统受信任的根证书列表中导⼊抓包⼯具⽣成的证书,⽽这个证书
会被浏览器信任,也就是抓包⼯具给⾃⼰创建了⼀个认证中⼼ CA,客户端拿着中间⼈签发的证书去中间⼈
⾃⼰的 CA 去认证,当然认为这个证书是有效的。
23.如何避免被中间⼈抓取数据
我们要保证⾃⼰电脑的安全,不要被病毒乘虚⽽⼊,⽽且也不要点击任何证书⾮法的⽹站,这样 HTTPS
数据就不会被中间⼈截取到了。
当然,我们还可以通过 HTTPS 双向认证来避免这种问题。
⼀般我们的 HTTPS 是单向认证,客户端只会验证了服务端的身份,但是服务端并不会验证客户端的身
份。
![image-20240811143821081](https://img-blog.csdnimg.cn/img_convert/c9d9571f888f5ad9144e7365eec57f4e.png)
如果⽤了双向认证⽅式,不仅客户端会验证服务端的身份,⽽且服务端也会验证客户端的身份。服务端⼀
旦验证到请求⾃⼰的客户端为不可信任的,服务端就拒绝继续通信,客户端如果发现服务端为不可信任
的,那么也中⽌通信。
HTTP/1.1、HTTP/2、HTTP/3 演变
24.HTTP/1.1 相⽐ HTTP/1.0 提⾼了什么性能?
HTTP/1.1 相⽐ HTTP/1.0 性能上的改进:
-
使⽤⻓连接的⽅式改善了 HTTP/1.0 短连接造成的性能开销。
-
⽀持管道(pipeline)⽹络传输,只要第⼀个请求发出去了,不必等其回来,就可以发第⼆个请求出
去,可以减少整体的响应时间。
但 HTTP/1.1 还是有性能瓶颈:
-
请求 / 响应头部(Header)未经压缩就发送,⾸部信息越多延迟越⼤。只能压缩 Body 的部分;
-
发送冗⻓的⾸部。每次互相发送相同的⾸部造成的浪费较多;
-
服务器是按请求的顺序响应的,如果服务器响应慢,会招致客户端⼀直请求不到数据,也就是队头阻
塞;
-
没有请求优先级控制;
-
请求只能从客户端开始,服务器只能被动响应。
25.HTTP/2 做了什么优化?
HTTP/2 协议是基于 HTTPS 的,所以 HTTP/2 的安全性也是有保障的。
那 HTTP/2 相⽐ HTTP/1.1 性能上的改进:
头部压缩
⼆进制格式
并发传输
服务器主动推送资源
26.HTTP/3 做了哪些优化?
前⾯我们知道了 HTTP/1.1 和 HTTP/2 都有队头阻塞的问题:
HTTP/1.1 中的管道( pipeline)虽然解决了请求的队头阻塞,但是没有解决响应的队头阻塞,因为服
务端需要按顺序响应收到的请求,如果服务端处理某个请求消耗的时间⽐较⻓,那么只能等响应完这
个请求后, 才能处理下⼀个请求,这属于 HTTP 层队头阻塞。
HTTP/2 虽然通过多个请求复⽤⼀个 TCP 连接解决了 HTTP 的队头阻塞 ,但是⼀旦发⽣丢包,就会
阻塞住所有的 HTTP 请求,这属于 TCP 层队头阻塞。
HTTP/2 队头阻塞的问题是因为 TCP,所以 HTTP/3 把 HTTP 下层的 TCP 协议改成了 UDP**!**
UDP 发送是不管顺序,也不管丢包的,所以不会出现像 HTTP/2 队头阻塞的问题。⼤家都知道 UDP 是不
可靠传输的,但基于 UDP 的 QUIC 协议 可以实现类似 TCP 的可靠性传输。
QUIC 有以下 3 个特点。
⽆队头阻塞
更快的连接建⽴
连接迁移
27.既然有HTTP协议,为什么还要有RPC?
纯裸 TCP 是能收发数据,但它是个⽆边界的数据流,上层需要定义消息格式⽤于定义消息边界。于
是就有了各种协议,HTTP 和各类 RPC 协议就是在 TCP 之上定义的应⽤层协议。
RPC 本质上不算是协议,⽽是⼀种调⽤⽅式,⽽像 gRPC 和 Thrift 这样的具体实现,才是协议,它
们是实现了 RPC 调⽤的协议。⽬的是希望程序员能像调⽤本地⽅法那样去调⽤远端的服务⽅法。同
时 RPC 有很多种实现⽅式,不⼀定⾮得基于 TCP 协议。
从发展历史来说,HTTP 主要⽤于 B/S 架构,⽽ RPC 更多⽤于 C/S 架构。但现在其实已经没分那么
**清了,**B/S 和 C/S 在慢慢融合。很多软件同时⽀持多端,所以对外⼀般⽤ HTTP 协议,⽽内部集群的
微服务之间则采⽤ RPC 协议进⾏通讯。
RPC 其实⽐ HTTP 出现的要早,且⽐⽬前主流的 HTTP/1.1 性能要更好,所以⼤部分公司内部都还在
使⽤ RPC。
HTTP/2.0 在 HTTP/1.1 的基础上做了优化,性能可能⽐很多 RPC 协议都要好,但由于是这⼏年才出
来的,所以也不太可能取代掉 RPC。
28.怎么建⽴WebSocket连接
![image-20240811151231151](https://img-blog.csdnimg.cn/img_convert/c82065b122b02588bee5e2b4f8ce1911.png)
![image-20240811151524183](https://img-blog.csdnimg.cn/img_convert/213d24c357c09682c3aa4a31794c44c1.png)
上⾯这张图就是全貌了,从截图上的注释可以看出,WebSocket和HTTP⼀样都是基于TCP的协议。经历了
三次TCP握⼿之后,利⽤ HTTP 协议升级为 WebSocket 协议。
你在⽹上可能会看到⼀种说法:“WebSocket 是基于HTTP的新协议”,其实这并不对,因为WebSocket只
有在建⽴连接时才⽤到了HTTP,升级完成之后就跟HTTP没有任何关系了。
29.WebSocket****的消息格式是怎样的
上⾯提到在完成协议升级之后,两端就会⽤webscoket的数据格式进⾏通信。
数据包在WebSocket中被叫做帧,我们来看下它的数据格式⻓什么样⼦。
WebSocket的数据格式也是数据头(内含payload⻓度) + payload data 的
形式。
这是因为 TCP 协议本身就是全双⼯,但直接使⽤纯裸****TCP去传输数据,会有粘包的"问题"。为了解决这个
问题,上层协议⼀般会⽤消息头****+****消息体的格式去᯿新包装要发的数据。
⽽消息头⾥⼀般含有消息体的⻓度,通过这个⻓度可以去截取真正的消息体。
HTTP 协议和⼤部分 RPC 协议,以及我们今天介绍的WebSocket协议,都是这样设计的。
30.WebSocket****的使⽤场景
WebSocket完美继承了 TCP 协议的全双⼯能⼒,并且还贴⼼的提供了解决粘包的⽅案。
它适⽤于需要服务器和客户端(浏览器)频繁交互的⼤部分场景,⽐如⽹⻚/⼩程序游戏,⽹⻚聊天室,以
及⼀些类似⻜书这样的⽹⻚协同办公软件。
回到⽂章开头的问题,在使⽤ WebSocket 协议的⽹⻚游戏⾥,怪物移动以及攻击玩家的⾏为是服务器逻辑
产⽣的,对玩家产⽣的伤害等数据,都需要由服务器主动发送给客户端,客户端获得数据后展示对应的效
果。