小林计网笔记-3.1HTTP常见面试题

3.1HTTP常见面试题

在这里插入图片描述

HTTP基本概念

HTTP是什么

HTTP是超文本传输协议,也就是HyperText Transfer Protocol
在这里插入图片描述

  • 协议:HTTP是一个用在计算机世界里的协议,它使用计算机能够理解的语言确立了一种计算机之间交流通信的规范(两个以上的参与者),以及相关的各种控制和错误处理方式(行为约定和规范)。
  • 传输

HTTP是一个双向协议,但半双工。
上网冲浪时,浏览器是请求方A,百度网站是应答方B。双方约定用HTTP协议来通信,于是浏览器把请求数据发送给网站,网站再把一些数据返回给浏览器,最后由浏览器渲染在屏幕,就可以看到图片、视频了。
在这里插入图片描述
数据虽然在A和B之间传输,但是允许中间有接力,而且在HTTP里,需要中间人遵从HTTP协议,只要不打扰基本的数据传输,就可以添加任意额外的东西。
HTTP是一个在计算机世界里专门用来在两点传输数据的约定和规范。

  • 超文本

HTTP传输的内容是超文本
超文本,超越了普通文本的文本,它是文字、图片、视频等的混合体,最关键的是有超链接,能从一个超文本跳转到另外一个超文本。
HTML就是最常见的超文本,它本身只是纯文字文件,但内部用很多标签定义了图片、视频等的链接,再经过浏览器的解释,呈现给我们的就是一个有文字、有画面的网页了。
HTTP是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范。
HTTP可用于从互联网服务器传输超文本到本地浏览器,也可以用于服务器和服务器之间。

HTTP常见的状态码有哪些?

在这里插入图片描述
1**类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。
2**类状态码表示服务器成功处理了客户端的请求。

  • [200OK]是最常见的成功状态码,表示一切正常。如果是非HEAD请求,服务器返回的响应头就会有body数据
  • [204No Content],常见成功状态码,与200OK基本相同,但响应头没有body数据
  • [206 Partial Content]是应用于HTTP分块下载或断点续传,表示响应返回的body数据并不是资源的全部,而是其中的一部分,也是服务器处理成功的状态。

3**类状态码表示客户端请求的资源发生了变动,说明请求的资源已经不存在了,需要用新的URL再次访问,也就是重定向

  • [301 Moved Permantly]表示永久重定向,说明请求的资源已经不存在了,需改新的URL再次访问。
  • [302 Found]表示临时重定向,说明请求的资源还在,但暂时需要用另一个URL访问
    301和302都会在响应头里使用字段Location,指明后续要跳转的URL,浏览器会自动重定向新的URL。
  • [304 Not Modified]不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称为缓存重定向,也就是告诉客户端可以继续使用缓存资源,用于缓存控制

4**类状态码表示客户端发送的报文有误,服务器无法处理,也就是错误的含义。

  • [400 Bad Request]表示客户端请求的报文有错误,但只是个笼统的错误。
  • [403 Forbidden]表示服务器禁止访问资源,并不是客户端的请求出错
  • [404 Not Found]表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端

5**类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。

  • [500 Internal Server Error]与400类型相似,是个笼统的错误,服务器发生了什么错误,我们并不知道
  • [501 Not Implemented]表示客户端请求的功能还不支持,类似“即将开业,敬请期待”。
  • [502 Bad Gateway]通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误
  • [503 Service Unavailable]表示服务器当前很忙,暂时无法响应客户端,类似“网络正忙,请稍后重试”

HTTP常见字段有哪些?

Host字段
客户端发送请求时,用来指定服务器的域名。

Host:www.A.com

有了Host字段,就可以将请求发往同一台服务器
在这里插入图片描述
Content-Length字段
服务器在返回数据时,会有Content-Length字段,表面本次回应的数据长度

Content-Length:1000

告诉浏览器,本次服务器回应的数据长度是1000字节,后面的字节就属于下一个回应了
在这里插入图片描述

HTTP是基于TCP传输协议进行通信的,而使用TCP传输协议,就会存在粘包问题。HTTP协议通过设置回车符、换行符作为HTTP header的边界,通过Content-Length字段作为HTTP body的边界,这两个方式都是为了解决粘包问题。
== Connection字段==
Connection字段最常用于客户端要求服务器使用HTTP长连接机制,以便其他请求复用。
HTTP长连接的特点是只要任意一端没有明确提出断开连接,则保持TCP连接状态。
在这里插入图片描述
在这里插入图片描述
HTTP/1.1版本的默认连接都是长连接,但为了兼容老版本HTTP,需要指定Connection首部字段的值为Keep-Alive

Connection:Keep-Alive

开启了 HTTP Keep-Alive机制后,连接就不会中断,而是保持连接。当客户端发送另一个请求时,他会使用同一个连接,一直持续到客户端或服务器端提出断开连接。
HTTP Keep-Alive和TCP KeepAlive不是一个东西
Content Type字段
Content Type字段用于服务器回应时,告诉客户端,本次数据是什么格式。

Content-Type:text/html;Charset=utf-8

上面的类型表明,发送的是网页,而且编码是UTF-8
客户端请求的时候,可以使用Accept字段声明自己可以接收哪些数据格式

Accept:*/*

上面代码中,客户端声明自己可以接收任何格式的数据
在这里插入图片描述
Content-Encoding字段
Content-Encoding字段说明数据的压缩方法,表示服务器返回的数据使用了什么压缩格式

Content-Encoding:gzip

上面表示服务器返回的数据采用了gzip方式压缩,告知客户端需要用此方式解压
客户端请求时,用Accept-Encoding字段说明自己可以接收哪些压缩方式

Accept-Encoding:gzip,deflate

在这里插入图片描述

GET与POST

GET和POST有什么区别?

根据RFC规范,GET的语义是从服务器获取指定的资源,这个资源可以是静态的文本、页面、图片视频等。GET请求的参数位置一般是写在URL中,URL规定只能支持ASCII,所以GET请求的参数只允许ASCII字符,而且浏览器会对URL的长度有限制(HTTP协议本身对URL长度并没有做任何规定)
打开小林的文章,浏览就会发送GET请求给服务器,服务器就会返回文章的所有文字及资源。
在这里插入图片描述
根据RFC规范,POST的语义是根据请求负载(报文body)对指定的资源做出处理,具体的处理方式视资源类型而不同。POST请求携带数据的位置一般都是写在报文body中,body中的数据可以是任意格式的数据,只要客户端与服务端协商好即可,而且浏览器不会对body大小做限制。
比如,我们在小林的文章底部,敲入了留言点击提交,浏览器就会执行一次POST请求,把你的留言文字放进了报文body里,然后拼接好POST请求头,通过TCP协议发送给服务器。
在这里插入图片描述

GET和POST方法都是安全和幂等的吗?

  • 安全:在HTTP协议里,安全是指请求方式不会破坏服务器上的资源
  • 幂等:多次执行相同的操作,结果都是相同的

根据RFC规范定义的语义来看:

  • GET方法是安全且幂等的,因为它是只读操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。所以,可以对GET请求的数据做缓存,这个缓存可以做到浏览器本身上(彻底避免浏览器发请求),也可以做到代理上(如nginx),而且在浏览器中GET请求可以保存为书签
    -POST因为是新增或提交数据的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不幂等。所以,浏览器一般不会缓存POST请求,也不能把POST请求保存为书签,
    小结:
    GET的语义是请求获取指定的资源,GET方法是安全、幂等、可被缓存的。
    POST的语义是根据请求负荷(报文主体)对指定的资源做出处理,具体的处理方式视资源类型而不同。POST不安全、不幂等,(大部分实现)不可被缓存。
    但在实际过程中,开发者不一定会按照RPC规范定义的语义来实现GET和POST方法:

  • 可以用GET方法实现新增或删除数据的请求,这样的实现自然就不是安全和幂等

  • 可以用POST方法实现查询数据的请求,这样实现的POST方法自然就是安全和幂等

如果“安全”放入概念是指信息是否会被泄漏的话,虽然POST用body传输数据,而GET用URL传输,这样数据会在浏览器地址栏容易看到,但是并不能说GET不如POST安全。因为HTTP传输的内容都是明文的,虽然在浏览器地址栏看不到POST提交的body数据,但是只要抓个包就能看到。所以,要避免传输过程中数据被窃取,就要使用HTTPS协议,这样所有HTTP数据都会被加密传输。
RFC规范并没有规定GET请求不能带body。理论上,任何请求都可以带body,只是因为RFC规范定义的GET请求是获取资源,根据这个语义不需要用到body.
另外,URL中的查询1参数也不是GET所独有的,POST请求的URL中也可以有参数。

HTTP缓存技术

HTTP缓存技术有哪些实现方式?

对于一些具有重复性的HTTP请求,比如每次请求得到的数据都是一样的,我们可以把这对【请求-响应】的数据都缓存在本地,那么下次直接读取本地的数据,不必通过网络获取服务器的响应。
缓存技术:强制缓存、协商缓存

什么是强制缓存?

强制缓存指的是只要浏览器判断缓存没有过期,则直接使用浏览器的本地缓存,决定是否使用缓存的主动性在于浏览器这边。
下图中,返回的是200状态码,但是size项中标识的是from disk cache,就是使用了强制缓存。
在这里插入图片描述
强制缓存是利用下面这两个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

什么是协商缓存?

当我们在浏览器使用开发者工具的时候,你可能会看到过某些请求的响应码是304,表示浏览器可以使用本地缓存的资源,通常这种通过服务端告知客户端是否可以使用缓存的方式被称为协商缓存。
在这里插入图片描述
协商缓存:与服务器协商之后,通过协商结果来判断是否直接使用本地缓存。
协商缓存可以基于两种头部来实现。
第一种:请求头部中If-Modified-Since字段与响应头部中的Last-Modified字段实现。

  • 响应头部中的Last-Modified表示这个响应资源的最后修改时间
  • 请求头部中的If-Modified-Since:当资源过期了,发现响应头中具有Last-Modified声明,则再次发起请求的时候带上Last-Modified的时间,服务器收到请求后发现有If-Modified-Since则与被请求资源的最后修改时间进行对比(Last-Modified),如果最后修改时间较新(大),说明资源又被改过,则返回新资源,HTTP 200OK;如果最后修改时间较旧(小),说明资源无新修改,响应HTTP304缓存。

第二种:请求头部中的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解决了Last-Modified几个比较难以解决的问题:

  • 在没有修改文件内容情况下文件的最后修改时间可能也会改变,这会导致客户端认为文件被改动了,从而重新请求
  • 可能有些文件是在秒级以内修改的,If-Modified-Since能检查到的粒度是秒级,使用Etag就能保证这种需求下客户端在1秒内能被刷新多次
  • 有些服务器不能精确获取文件的最后修改时间

协商缓存的这两个字段都需要配合强制缓存中的Cache-Control字段来使用,只有在未命中强制缓存的时候,才能发起带有协商缓存字段的请求。
在这里插入图片描述
当使用ETag字段实现协商缓存的过程:

  • 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在Response头部加上ETag唯一标识,这个唯一标识的值是根据当前请求的资源生成的
  • 当浏览器再次请求访问服务器中的该资源时,首先会检查强制缓存是否过期:
    (1)如果没有过期,则直接使用本地缓存
    (2)如果缓存过期了,会在Response头部加上If-None-Match字段,该字段的值就是ETag唯一标识
  • 服务器再次收到请求后,会根据请求中的If-None-Match值与当前请求的资源生成的唯一标识进行比较
    (1)如果值相等,则返回304 Not Modified,不会返回资源
    (2)如果不相等,则返回200状态码和资源,并在Response头部加上新的ETag唯一标识
  • 如果浏览器收到304的请求响应状态码,则会从本地缓存中加载资源,否则更新资源

HTTP特性

目前为止,HTTP常见版本有HTTP/1.1,HTTP/2.0,HTTP/3.0,不同版本的HTTP特性是不一样的,先介绍HTTP/1.1版本特性。

HTTP/1.1的优点有哪些?

HTTP最突出的优点是简单、灵活和易于扩展、应用广泛和跨平台。
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的应用遍地开花,同时天然具有跨平台的优越性。

HTTP/1.1的缺点有哪些?

HTTP协议里有优缺点一体的双刃剑,分别是:无状态、明文传输,同时还有一大缺点:不安全
1、无状态双刃剑
好处:服务器不会去记忆HTTP的状态,所以不需要额外的资源记录状态信息,这能减轻服务器的负担,能够把更多的CPU和内存用来对外提供服务。
坏处:既然服务器没有记忆能力,它在完成有关联性的操作时会非常麻烦。
例如登录->添加购物车->下单->结算->支付,这系列操作都要知道用户身份才行。但服务器不知道这些请求是有关联的,每次都要问一遍身份信息。
这样每操作一次,都要验证信息,购物体验不愉快。
对于无状态的问题,比较简单的解决方式:Cookie技术
Cookie通过在请求和响应报文中写入Cookie信息来控制客户端的状态。
在客户端第一次请求后,服务器会下发一个装有客户信息的“小贴纸”,后续客户请求服务器的时候,带上“小贴纸”,服务器就能认得了。
在这里插入图片描述

2、明文传输双刃剑
明文意味着在传输过程中的信息,是可方便阅读的,比如Wireshark抓包都可以直接肉眼查看,为我们调试工作带来了极大的便利性。
但是HTTP的所有信息都暴露,相当于信息裸奔。传输时信息毫无隐私可言,容易被窃取,如果里面有你的账号密码信息,那号就没了。

3、不安全
HTTP比较严重的缺点就是不安全。

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

HTTP的安全问题,可以用HTTPS的方式解决,通过引入SSL\TLS层,使得在安全上达到了极致,

HTTP/1.1性能如何?

HTTP协议是基于TCP/IP,并且使用了请求-应答的通信模式,所以性能的关键就在这两点里面。
1、长连接
早期HTTP/1.0性能上的一个很大的问题,就是每次发起一个请求,都要新建一次TCP连接(三次握手),而且是串行请求,做了无谓的TCP连接建立和断开,增加了通信开销。
为了解决上述TCP连接问题,HTTP/1.1 提出了长连接的通信方式,也叫持久连接。长连接的好处在于减少了TCP连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。
持久连接的特点是:只要任意一端没有明确提出断开连接,则保持TCP连接状态。
如果某个HTTP长连接超过一定时间没有任何数据交互,服务端就会主动断开这个连接。
在这里插入图片描述

2、管道网络传输
HTTP/1.1采用了长连接的方式,使得管道(pipe)网络传输成为了可能。
在同一个TCP连接里面,客户端可以发起多个请求,只要第一个请求发出去了,不必等其回来,就可以发送第二个请求出去,可以减少整体的响应时间。
举个栗子,客户端需要请求两个资源。以前的做法,在同一个TCP连接里面,先发送A请求,然后等待服务器做出回应,收到后再发出B请求。管道机制则允许浏览器同时发出A请求和B请求,如下图:
在这里插入图片描述
但是服务器必须按照接收请求的顺序发送这些管道化请求的响应。
如果服务端在处理A请求时耗时比较长,那么后续的请求的池里都会被阻塞,称为队头阻塞
HTTP/1.1管道解决了请求的队头阻塞,但是没有解决响应的队头阻塞。
注意:HTTP/1.1管道化技术不是默认开启,而且浏览器基本都没有支持,所以后面章节讨论HTTP/1.1都建立在没有使用管道化的前提。有这个功能,但是没有被使用。

3、队头阻塞
请求-应答的模式会造成HTTP的性能问题。
当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一同被阻塞了,会招致客户端一直请求不到数据,造成队头阻塞
在这里插入图片描述
总之HTTP/1.1性能一般般,后续的HTTP/2和HTTP/3就是在优化HTTP的性能。

HTTP与HTTPS

HTTP与HTTPS有哪些区别?

  • HTTP是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS则解决HTTP不安全的缺陷,在TCP和HTTP网络层之间加入了SSL/TLS安全协议,使得报文能够加密传输。
  • HTTP连接建立相对简单,TCP三次握手之后便可进行HTTP的报文传输,而HTTPS在TCP三次握手之后,还需进行SSL/TLS的握手过程,才可进入加密报文传输。
  • 两者的默认端口不一样,HTTP默认端口号是80,HTTPS默认端口号是443.
  • HTTPS协议需要向CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。

HTTPS解决了HTTP的哪些问题?

HTTP由于是明文传输,所以安全上存在以下三个风险

  • 窃听风险
  • 篡改风险
  • 冒充风险

HTTPS在HTTP与TCP层之间加入了SSL\TLS协议,可以很好的解决上述的风险
在这里插入图片描述

  • 信息加密
  • 校验机制
  • 身份证书
    只要自身不作恶,SSL\TLS协议是能保证通信是安全的
    HTTPS是如何解决上面三个风险的?
  • 混合加密,实现信息的机密性,解决窃听风险
  • 摘要算法,实现完整性,它能够为数据生成独一无二的指纹,解决篡改风险
  • 将服务器公钥放入到数字证书中,解决冒充风险

1、混合加密
HTTPS采用对称加密+非对称加密的混合加密方式。

  • 在通信建立前采用非对称加密的方式交换会话密钥,后续就不在使用非对称加密
  • 在通信过程中全部使用对称加密的会话密钥的方式加密明文数据
    采用混合加密方式的原因:
  • 对称加密只使用一个密钥,运算速度快,密钥必须保密,无法做到安全的密钥交换
  • 非对称加密使用两个密钥:公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但速度慢
    在这里插入图片描述

2、摘要算法+数字签名
理解:为了保证传输的内容不被篡改,我们需要对内容计算出一个指针,然后同内容一起传输给对方;对方收到后,先是对内容也计算一个指针,然后跟发送方发送的指针做一个比较,如果指针相同,说明内容没有被篡改,否则就可以判断内容被篡改了。
计算机里会用摘要算法(哈希函数)来计算出内容的哈希值,也就是内容的指纹,这个哈希值是唯一的,且无法通过哈希值推导出内容。
在这里插入图片描述
通过哈希算法可以确保内容不会被篡改,但是并不能保证内容+哈希值不会被中间人替换,因为这里缺少对客户端收到的消息是否来源于服务端的证明。
为避免这种情况,计算机使用非对称加密算法来解决,共有两个密钥:

  • 公钥:公开给所有人
  • 私钥:必须由本人管理,不可泄漏

这两个密钥可以双向加解密的,比如可以用公钥加密内容,然后私钥解密,也可以用私钥加密内容,公钥解密内容

  • 公钥加密,私钥解密:保证内容传输的安全, 因为被公钥加密的内容,其他人是无法解锁的,只要持有私钥的人,才能解密出实际的内容
  • 私钥加密,公钥解密:保证消息不会被冒充,因为私钥是不可泄密的,如果公钥能正常解密出私钥加密的内容,就能证明这个消息是来源于持有私钥身份的人发送的

一般我们不会用非对称加密来加密实际的传输内容,因为非对称加密的计算机比较耗费性能的。
所以非对称加密的用途主要在于通过私钥加密,公钥解密的方式,来确认消息的身份,即数字签名算法。私钥加密内容不是内容本身,而是对内容的哈希值的加密
在这里插入图片描述
私钥是由服务器保管,然后服务端会向客户端颁发对应的公钥。如果客户端收到的信息,能被公钥解密,就说明该消息是由服务器发送的。

3、数字证书

  • 通过哈希算法来保证消息的完整性
  • 通过数字签名来保证消息的来源可靠性(能确认消息是由持有私钥的一方发送的)

但还缺少身份验证的环节,万一公钥是被伪造的呢?(自己伪造出一对公私钥)
通过权威机构CA(数字证书认证机构),将服务器公钥放在数字证书(由数字证书认证机构颁发)中,只要证书是可信的,公钥就是可信的。
通过数字证书的方式保证服务器公钥的身份,解决冒充的风险。
在这里插入图片描述

HTTPS是如何建立连接的?其间交互了什么?

SSL/TLS协议基本流程:

  • 客户端向服务端索要并验证服务器的公钥
  • 双方协商生产会话密钥
  • 双方采用会话密钥进行加密通信

前两步就是SSL\TLS的建立过程,也就是TLS握手阶段
TLS的握手阶段涉及四次通信,使用不同的密钥交换算法,TLS握手的流程也会不一样的,常用的密钥交换算法RAS算法和ECDHE算法
基于RAS算法的TLS握手过程:(前向安全问题)
1、ClientHello
首先,由客户端向服务器发起加密通信请求,ClientHello请求
客户端向服务器发送以下信息:
(1)客户端支持的TLS协议版本,如TLS 1.2版本
(2)客户端生产的随机数(Client Random),后用于生成会话密钥条件之一
(3)客户端支持的密码套件列表,如RSA加密算法

2、SeverHello
服务器收到客户端请求后,向客户端发出响应,ServerHello
服务端回应的内容如下:
(1)确认TLS协议版本,如果浏览器不支持,则关闭加密通信
(2)服务器生产的随机数(Server Random),也是后面用于生产会话密钥的条件之一
(3)确认密码套件列表,如RSA加密算法
(4)服务器的数字证书

3、客户端回应
客户端收到服务器的回应之后,首先通过浏览器或操作系统中的CA公钥,确认服务器的数字证书的真实性
如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后使用它加密报文,向服务器发送如下消息:
(1)一个随机数(pre-master key),该随机数会被服务器公钥加密
(2)加密通信算法改变通知,表示随后的信息都将用会话密钥加密通信
(3)客户端握手结束通知,表示客户端的握手阶段已经结束,这一项同时把之前所有内容的发生的数据做个摘要,用来供服务器校验。
pre-master key是整个握手阶段的第三个随机数,会发给服务器,所以整个随机数客户端和服务端都是一样的
服务器和客户端有了三个随机数(Client Random、Server Random、pre-master key),接着就用双方协商的加密算法,各自生成本次通信的会话密钥。

4、服务器的最后回应
服务器收到客户端的第三个随机数(pre-master key)之后,通过协商的加密算法,计算出本次通信的会话密钥。
然后,向客户端发送最后的信息:
(1)加密通信算法改变通知,表示随后的信息都将用会话密钥加密通信
(2)服务器握手结束通知,表示服务器的握手阶段已经结束,这一项同时把之前所有内容的发送的数据做个摘要,用来供客户端校验。

至此,整个TLS的握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用会话密钥加密内容。

HTTPS的应用数据是如何保证完整性的?

TLS在实现上分为握手协议记录协议两层:

  • TLS握手协议就是TLS四次握手的过程,负责协商加密算法和生成对称密钥,后续用此密钥来保护应用程序数据(即HTTP数据)
  • TLS记录协议负责保护应用程序数据并验证其完整性和来源,所以对HTTP数据加密是使用记录协议

TLS记录协议1主要负责消息(HTTP数据)的压缩,加密及数据的认证:

  • 消息被分割成多个较短的片段,然后分别对每个片段进行压缩
  • 经过压缩的片段会被加上消息认证码(MAC码,通过哈希算法生成),用于保证完整性、进行数据认证。通过附加消息认证码的MAC值,可以识别出篡改。为了防止重放攻击,在计算消息认证时,还加上了片段的编码
  • 经过压缩的片段再加上消息认证码会一起通过对称密码进行加密
  • 经过加密的数据再加上由数据类型、版本号、压缩后的长度组成的报头就是最终的报文数据。

在这里插入图片描述
记录协议完成后,最终的报文数据将传递给传输控制协议TCP层传输

HTTPS一定安全可靠吗?

在这里插入图片描述

客户端通过浏览器向服务器发起HTTPS请求,被假基站转发到一个中间人服务器,于是客户端是和中间人服务器完成TLS握手,然后这个中间人服务器再与真正的服务器完成TLS握手。
具体过程:

  • 客户端向服务器发起HTTPS建立连接请求时,然后被假基站转发到了一个中间人服务器,接着中间人向服务端发起HTTPS建立连接请求,此时客户端与中间人进行TLS握手,中间人与服务端进行TLS握手
  • 在客户端与中间人进行TLS握手过程中,中间人会发送自己的公钥给客户端,客户端验证证书的真伪,然后从证书拿到公钥,并生成一个随机数,用公钥加密随机数发给中间人,中间人使用私钥解密,得到随机数,此时双方都有随机数,然后通过算法生成对称加密密钥A,后续客户端与中间人通信就用这个对称加密密钥来加密数据
  • 在中间人与服务端进行TLS握手过程中,服务器会发送从CA机构签发的公钥证书给中间人,从证书拿到公钥,并生成一个随机数,用公钥加密随机数发给服务端,服务端用私钥解密,得到随机数,此时双方都有随机数,然后通过算法生成对称加密密钥B,后续中间人与服务端通信就用这个对称加密密钥来加密数据
  • 后续的通信过程中,中间人用对称加密密钥A解密客户端的HTT[S请求的数据,然后用对称加密密钥B加密HTTPS请求后,转发给服务器,接着服务器发送HTTPS响应数据给中间人,中间人用对称加密密钥B解密HTTPS响应数据,然后用对称加密密钥A加密后,转发给客户端

在这里插入图片描述
从客户端的角度看,其实并不知道中间人服务器这个角色。中间人可以解开浏览器发起的HTTPS请求里的数据,也可以解开服务器响应给浏览器的HTTPS响应数据。中间人可以偷看浏览器与服务端之间的HTTPS请求和响应的数据。
但是发生这样场景是有前提的,前提是用户点击接受了中间人服务器的证书。
中间人服务器与客户端在TLS握手过程中,实际上发送了自己伪造的证书给浏览器,而这个伪造的证书是能被浏览器(客户端)识别出是非法的,于是就会提醒用户该证书存在问题。
在这里插入图片描述
如果用户执意点击【继续浏览此网站】,相当于用户接受了中间人伪造的证书,那么后续整个HTTPS通信都能被中间人监听了
所以,这其实并不能说HTTPS不够安全,比较浏览器都已经提示证书有问题了,如果用户坚决要访问,那就不能怪HTTPS
另外,如果你的电脑中毒了,被恶意导入了中间人的根证书,那么在验证中间人的证书时,由于你的操作系统信任了中间人的根证书,那么等同于中间人的证书是合法的,在这种情况下,不会弹出证书存在问题的风险提示,
这其实也不关HTTPS的事情,是你电脑中毒了才导致HTTPS数据被中间人劫持的。
所以,HTTPS协议本身到目前为止还是没有任何漏洞的,即使你成功进入中间人攻击,本质上是利用了客户端的漏洞(用户点击继续访问或者恶意导入伪造的证书),并不是HTTPS不够安全。

  • 为什么抓包工具能截取HTTPS数据?

很多抓包工具之所以可以明文看到HTTPS数据,工作原理与中间人一致的
对于HTTPS连接来说,中间人要满足以下两点,才能实现真正的明文代理:
1、中间人,作为客户端与真实服务端建立连接这一步不会有问题,因为服务端不会校验客户端的身份
2、中间人,作为服务端与真实客户端建立连接,这里会有客户端信任服务端的问题,也就是服务端必须有对应域名的私钥
中间人要拿到私钥只能通过如下方式:
1、去网站服务器端拿到私钥
2、去CA处拿域名签发私钥
3、自己签发证书,切要被浏览器信任
抓包工具只能使用第三种方式取得中间人的身份
使用抓包工具进行HTTPS抓包的时候,需要在客户端安装Fiddler的根证书,这里实际上起认证中心的作用
使用抓包工具能够抓包的关键是客户端会往系统受信任的根证书列表中导入抓包工具生成的证书,而这个证书会受浏览器信任,也就是抓包工具给自己创建了一个认证中心CA,客户端拿着中间人签发的证书去中间人自己的CA去认证,当然认为这个证书是有效的。

  • 如何避免被中间人抓取数据?

我们要保证自己电脑的安全,不要被病毒乘虚而入,而且也不要点击任何证书非法的网站,这样HTTPS数据就不会被中间人截取到了
我们还可以通过HTTPS双向认证来避免这种问题。
一般我们的HTTPS是单向认证,客户端只会验证服务端的身份,但是服务端并不会验证客户端的身份。
在这里插入图片描述
如果用了双向认证方式,不仅客户端会验证服务端的身份,而且服务端也会验证客户端的身份。服务端一旦验证到请求自己的客户端为不可信任,服务端就拒绝继续通信,客户端如果发现服务端为不可信任的,那么也中止通信。

HTTP/1.1、HTTP/2、HTTP/3演变

HTTP/1.1相比HTTP/1.0提高了什么性能?

HTTP/1.1相比HTTP/1.0性能上的改进:

  • 使用长连接的方式改善了HTTP/1.0短连接造成的性能开销
  • 支持管道(pipeline)网络传输,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间
    但HTTP/1.1还是有性能瓶颈:
  • 请求/响应头部(Header)未经压缩就发送,首部信息越多延迟越大,只能压缩Body的部分
  • 发送冗长的首部,每次互相发送相同的首部会造成的浪费较多
  • 服务器是按请求的顺序来响应的,如果服务器响应慢,会招致客户端一直请求不到数据,也就是队头阻塞
  • 没有请求优先级控制
  • 请求只能从客户端开始,服务器只能被动响应

HTTP/2做了什么优化?

HTTP/2协议是基于HTTPS的,所以HTTP/2的安全性也是有保障的。
在这里插入图片描述

HTTP/2相比HTTP/1.1性能上的改进:

  • 头部压缩
  • 二进制格式
  • 并发传输
  • 服务器主动推送资源

1、头部压缩
HTTP/2会压缩头(Header),如果你同时发出多个请求,它们的头是一样的或者相似的,那么,协议会帮你消除重复的部分。
这就是所谓的HPACK算法:在客户端和服务器同时维护一张头信息表,所有字段存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。

2、二进制格式
HTTP/2不再像HTTP/1.1里的纯文本形式的报文,而是全面采用二进制格式,头信息和数据体都是二进制,并且通称为帧(frame):头部信息帧(Headers Frame)和数据帧(Data Frame).
在这里插入图片描述
计算机收到报文后,无需再将明文的报文转成二进制,而是直接解析二进制报文,增加数据传输的效率。
比如状态码200,在HTTP/1.1是用’2’‘0’'0’三个字符来表示(二进制:00110010 00110000 00110000),共用3个字节
在这里插入图片描述
在HTTP/2,对于状态码200的二进制编码是10001000,只用了1字节就能表示,相比于HTTP/1.1/节省了2个字节,如下图:
在这里插入图片描述
Header:status:200 OK的编码内容为:1000 1000.表达含义:
在这里插入图片描述
1、最前面的1标识该Header是静态表中已经存在的KV
2、静态表中,status:200 OK静态表编码是8,二进制即是1000
因此,整体加起来就是1000 1000

3、并发传输
HTTP/1.1的实现是基于请求-响应模型的。同一连接中,HTTP完成一个事务(请求与连接),才能处理下一个事务,也就是说在发出请求等待响应的过程中,是没办法做其他事情的,如果响应迟迟不来,那么后续的请求是无法发送的,也造成了队头阻塞的问题。
HTTP/2引出了Stream概念,多个Stream复用一条TCP连接。
在这里插入图片描述
1个TCP连接包含多个Stream,Stream里可以包含1个或多个Message,Message对应HTTP/1.1/中的请求或响应,由HTTP头部或包体构成。Message里包含一个或者多个Frame,Frame是HTTP/2最小单位,以二进制压缩格式存放HTTP/1.1中的内容(头部或包体)
针对不同的HTTP请求用独一无二的Stream ID来区分,接收端可以通过Stream ID有序组装成HTTP消息,不同Stream的帧是可以乱序发送的,因此可以并发不同的Stream,也就是HTTP/2可以并行交错地发送请求和响应。
在这里插入图片描述
服务区并行交错地发送两个响应:Stream1 和Stream3,这两个Stream都是跑在一个TCP连接上,客户端收到后,会根据相同地Stream ID有序组装成HTTP消息。

4、服务器主动推送资源
HTTP/2还在一定程度上改善了传统地请求-应答工作模式,服务器不再是被动地响应,可以主动向客户端发送消息。
客户端和服务器双方都可以建立Stream,客户端建立地Stream必须是奇数号,服务器建立的Stream必须是偶数号。
在这里插入图片描述
上图中,Stream1是客户端向服务端请求的资源,属于客户端建立的Stream,所以该Stream的ID是奇数(1);Stream 2和4都是服务器主动向客户端推送的资源,属于服务器建立的Stream,所以这两个Stream ID是偶数(2和4)。
在这里插入图片描述
客户端通过HTTP/1.1请求从服务器那获取HTML文件,而HTML可能还需要依赖CSS渲染页面,这时客户端还要再发起获取CSS文件的请求,需要两次消息往返;在HTTP/2中,客户端在访问HTML时,服务器可以直接主动推动CSS文件,减少了消息传递的次数。

  • HTTP/2有什么缺陷?

HTTP/2通过Stream的并发能力,解决了HTTP/1队头阻塞,但是HTTP/2还是存在队头阻塞问题,问题是在TCP层面。
HTTP/2是基于TCP协议来传输数据的,TCP是字节流协议,TCP层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给HTTP应用,那么当前一个字节数据没有到达时,后收到的字节数据只能存放在内核缓冲区里,只有等到这1个字节数据到达时,HTTP/2应用层才能从内核中拿到数据,这就是HTTP/2的队头阻塞问题。
在这里插入图片描述
在这里插入图片描述

上图中发送方发送了很多packet,每个packet都有自己的序号,可以认为是TCP序号,其中packet3在网络中丢失了,即使packet4-6被接收方收到后,由于内核中的TCP数据不是连续的,于是接收方的应用层就无法从内核中读取到,只有等到packet3重传后,接收方的应用层才可以从内核中读取数据,这就是HTTP/2的队头阻塞问题,是在TCP层面发生的。
所以,一旦发生了丢包现象,就会触发TCP重传机制,这样在一个TCP连接中所有的HTTP请求都必须等待这个丢了的包被重传回来。

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个特点:

  • 无队头阻塞
  • 更快的连接建立
  • 连接迁移

1、无队头阻塞
QUIC协议也有类似于HTTP/2 Stream与多路复用的概念,也是可以在同一条连接上并发传输多个Stream,Stream可以认为就是一条HTTP请求。
QUIC有自己的一套机制可以保证传输的可靠性。当某个流发生丢包时,只会阻塞这个流,其他的流不会受到影响,因此不存在队头阻塞问题。这与HTTP/2不同,HTTP/2只要某个流中的数据包丢失了,其他流也会因此受到影响。
所以,QUIC连接上的多个Stream之间没有依赖,都是独立的,某个流丢失了,只会影响该流,其他流不受影响。
在这里插入图片描述

2、更快的连接建立
对于HTTP/1和HTTP/2协议,TCP和TLS是分层的,分别属于内核实现的传输层和openssl库实现的表示层,因此它们难以合并在一起,需要分批来握手,先TCP握手,再TLS握手。
HTTP/3在传输数据前虽然需要QUIC协议握手,但是这个握手过程只需要1RTT,握手的目的是为确认双方的连接ID,连接迁移就是基于连接ID实现的。
但是HTTP/3的QUIC协议并不是TLS分层,而是QUIC内部包含了TLS,它在自己的帧会携带TLS里的记录,再加上QUIC使用的是TLS/1.3,因此只需1RTT就可以同时完成建立连接与密钥协商。
在这里插入图片描述

甚至,在第二次连接的时候,应用数据包可以和QUIC握手信息(连接信息+TLS信息)一起发送,达到0RTT效果。
HTTP/3当会话恢复时,有效负载数据与第一个数据包一起发送,可以做到0RTT.
在这里插入图片描述

3、连接迁移
基于TCP传输协议的HTTP协议,由于是通过四元组(源IP、源端口、目的IP、目的端口)确定一条TCP连接。
在这里插入图片描述
那么当移动设备的网络从4G切换到Wifi时,意味着IP地址变化了,那么必须要断开连接,然后重新建立连接。而建立连接的过程包含TCP三次握手和TLS四次握手的时延,以及TCP慢启动的减速过程,给用户的感觉就是网络突然卡顿了一下,因此连接迁移成本是很高的。
而QUIC协议没有用四元组的方式来绑定连接,而是通过连接ID来标记通信的两个端点,客户端和服务端可以各自选择一组ID标记自己,因此即使移动设备的网络变化后,导致IP地址变化,只要仍保有上下文信息(比如连接ID、TLS密钥等),就可以无缝地复用原连接,消除重连地成本,没有丝毫卡顿感,达到连接迁移地功能。
QUIC是一个在UDP之上的伪TCP+TLS+HTTP/2的多路复用协议。
QUIC是新协议,对于很多网络设备,根本不知道什么是QUIC,只会当作UDP,这样会出现新的问题,因为有的网络设备是会丢掉UDP包的,而QUIC是基于UDP的,那么如果网络设备无法识别这是个QUIC包,那么就会当作UDP包,然后被丢弃。
HTTP/3现在普及的进度非常缓慢,不知道未来UDP是否能够逆袭TCP。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值