Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前端需要知道的网络基础 #10

Open
chiwent opened this issue Mar 15, 2019 · 3 comments
Open

前端需要知道的网络基础 #10

chiwent opened this issue Mar 15, 2019 · 3 comments
Labels

Comments

@chiwent
Copy link
Owner

chiwent commented Mar 15, 2019

前端需要知道的网络基础

本issue的内容主要是前端会接触到的一些网络知识,会有后续更新

@chiwent chiwent added the 网络 label Mar 15, 2019
@chiwent
Copy link
Owner Author

chiwent commented Mar 15, 2019

HTTPS的原理

HTTPS是建立在HTTP原有的基础上,在应用层加入TLS/SSL协议加密数据,来达到数据加密的目的。对比起HTTP协议来说,有以下优势:

  • 数据的完整性:传输的内容都经过了完整性校验
  • 数据隐私性:传输的内容经过了对称加密,每个连接都会生成一个唯一的加密密钥
  • 身份验证:第三方无法伪造服务端或客户端的身份

HTTPS的结构如下:
image

介绍HTTPS的具体工作原理前,先介绍一些常见的加密算法:

  • 非对称加密:RSA、DSA、ECC
  • 对称加密:AES、DES、3DES、ChaCha20-Poly1305
  • hash(散列)算法(严格来说不算加密):MD5、SHA1、SHA2、SHA256

对称加密和非对称加密算法的比较:

对称加密算法的密钥管理较难,不适合在互联网上传播,安全性低于非对称加密,但是加密和解密的速度比非对称加密的快,适合大数据量的加密;非对称加密的特点正好与对称加密算法相反

TLS/SSL使用了非堆成加密、对称加密和hash算法。

HTTPS的工作流程

现在,我们逐一分析一下https的工作流程

在不引人https而使用http的时候,信息都是通过明文的形式传播的。此时,传输的信息可能被中间人恶意截取或篡改,这就是中间人攻击。这时,我们很自然地会想到数据的加密传输。

由于在网上传输的数据量级可能会很大,我们首先想到的是使用非对称加密算法对信息进行加密,发送和接收方可以通过相同的密钥进行加密和解密。但是这样仍有缺陷,假如中间人在第一次通信的时候就将约定的密钥截获了,那么中间人就可以用这个密钥对数据进行加密和解密了。

这时,我们就要考虑怎么来保护对称加密的密钥了。我们可以引用非对称加密,来保护对称加密的密钥传输。在非对称加密中,包含一个公钥和私钥,明文可以通过公钥加密,然后用私钥解密;也可以通过私钥加密,用公钥解密。一切就绪,走流程:

  • 在建立通信时,服务端先将自己的公钥发送给客户端。
  • 客户端接收到公钥后,生成一个对称加密的密钥,并将刚刚收到的公钥对密钥进行加密,发送给服务端。
  • 服务端接收到后,用自己的私钥对接收的数据进行解密,拿到对称加密的密钥,然后双方就可以用这个密钥进行数据加密了。

然而,这方案也有和前面同样的缺陷,如果中间人在建立通信的时候,对接收方发送的公钥进行篡改,那么后续的操作就没有意义了。

这时候我们就需要引入第三方,权威的证书颁发机构(CA)来对进行加密传输了。

这个流程是这样的:

  • 服务端端先将自己的公钥KEY1发送给CA,向CA申请证书
  • CA有自己的一套非对称加密算法,它用自己的私钥来加密接收端发来的公钥KWY1,并通过服务端网址等信息生成一个证书签名,并用自己的私钥对证书签名进行加密。制作完成后,CA将证书发送给服务端
  • 当客户端向服务端发送通信请求时,服务端不直接返回自身的公钥KEY1,而是将自己申请的证书返回给客户端
  • 客户端接收到证书后,先判断证书的可靠性(浏览器和操作系统已经维护了所有权威的证书机构和公钥),客户端只要知道是哪个机构颁发的证书,就可以对应在本地找到相关的机构公钥,解密得到证书签名
  • 客户端用同样的规则生成证书签名,如果前后两个签名是一致的,就说明证书有效。验证通过后,客户端就可以使用机构的公钥解密得到服务端的公钥KEY1
  • 客户端用自身的对称加密密钥KEY2对服务端的公钥KEY1进行加密,发送给服务端
  • 服务端收到后用自己的私钥解密,得到了对称加密密钥KEY2,然后双方就可以用KEY2对传输的数据进行加密了

引用某博客的一张图片:
image
来自:https://www.cnblogs.com/ttltry-air/archive/2012/08/20/2647898.html

由于服务端在向CA申请证书的时候,会向CA发送自身的网址等信息,并通过了机构私钥加密,所以中间人是无法通过自己申请的证书来顶替的。

补充

证书的获取有3种途径:

  • 使用在线证书生成器
  • 自签名证书,如openssl工具可以本地生成证书
  • 数字证书认证机构(CA),如Let's Encrypt

参考:

@chiwent
Copy link
Owner Author

chiwent commented Mar 15, 2019

强缓存和协商缓存

这里提到的缓存不是指cookie、storage之类的存储介质,而是指服务端返回给客户端的HTTP报文头信息中的缓存信息,这些缓存信息是后台配置的(所以严格来说是后台的知识,笑~)。

当有了这部分的信息,客户端可以根据对应的规则来重新向后台发起请求获取数据,或者是使用缓存的数据。

强缓存和协商缓存的区别:

类型 获取方式 状态码 是否发送请求到服务器
协商缓存 从缓存中获取 304 是,请求服务器获知缓存是否可用
强缓存 从缓存中获取 200 否,在缓存数据未失效时,直接从缓存中取

两种缓存可以同时存在,强缓存的优先级要高于协商缓存。如果命中强缓存,那么直接使用缓存,不再执行协商缓存。


强缓存

强缓存是通过Expires或者Cache-Control来控制的,二者都是表示资源在客户端的缓存有效期。

Expires是HTTP1.0提出的,它是一个由GMT表示的绝对时间,基本的原理是:浏览器首次向服务端发起请求,服务器在返回资源时,在返回的报文header加上Expires。浏览器在接收到资源后,将对应的header也缓存下来。当浏览器再次请求这个资源的时候,先从缓存中查找,如果找到这个资源,并将其Expires和当前的请求时间进行比较,如果请求时间在Expires的指定时间内,则使用本地缓存;如果不是,浏览器从服务器获取资源,并更新Expires

Expires的缺点:

  • 浏览器和服务器时间不同步
  • 缓存过期后,无论文件是否发生变化,服务器都会再次读取文件返回给浏览器

Cache-Control是HTTP1.1提出的,可以通过max-age来设置缓存有效期,它是一个相对时间,在判断缓存的有效性时,都是根据客户端的时间进行判断的(避免一些跨时区的时间对称问题),所以比起Expires,更加有效。在二者同时存在的时候,Cache-Control的优先级高于Expires

协商缓存

执行强缓存规则时都是根据有效时间来判断的,如果时间过期后,并且文件没有改动,再次去获取文件就有点浪费服务器资源了。所以,此时我们可以考虑使用协商缓存。

和协商缓存相关的header有:

  • Last-Modifiedif-Modified-Since
    二者都是GMT格式的时间。浏览器在首次向服务器请求某个资源时,服务器在返回的报文头部会加上Last-Modified这个信息,它代表该资源在服务器上最后修改的时间;浏览器向服务器发起请求获取这个资源时,会在请求的header头上加上If-Modified-Since,它等于上一次请求时返回的Last-Modified。服务器再次收到请求时,会根据浏览器提供的If-Modified-Since和资源在服务器上最后修改的时间进行比对,判断资源是否有修改,如果没有变换则返回304状态码,但是不返回资源本身;如果有变化,则返回资源本身。当浏览器获取的是304时,则返回报文的头部不会加上Last-Modified,所以也不会改动它的值。如果没有命中缓存,浏览器再次向服务器请求该资源,Last-ModifiedIf-Modified-Since再次更新
  • ETagIf-Node-Match
    二者的值是服务器对某个资源生成的唯一标识,只要对应的资源有变化则该标识也会改变。其使用规则和前面的两个类似,不同之处在于,当服务器返回的是304状态码,由于服务端Etag已经重新更新了,服务器发送给浏览器的报文头还是会带有新的ETag

虽然Last-ModifiedETag在规则上很相似,实际上,后者的可靠性要高于前者。
Last-ModifiedETag同时存在时,服务器会优先验证ETag,在一致的情况下,才会继续对比Last-Modified

用户行为对缓存的影响:
image


参考:

@chiwent
Copy link
Owner Author

chiwent commented Mar 17, 2019

HTTP2的基本介绍

在HTTP2诞生前,HTTP1(包括HTTP1.0合HTTP1.1)已经服务我们很多年了。但是它的设计缺陷随着互联网的发展被不断放大,人们就这些问题开始设计改良方案。
2009年,谷歌的工程师提出了一种HTTP的替代方案。后来,人们在其设计的基础上开发了HTTP2。

HTTP1的问题

1.队头阻塞

一般来说,浏览器向服务端请求的资源不止一份,并且,多数情况下它希望能同时获取许多资源。如果在一个网站内,其所有资源都放在了单个域名下,HTTP1无法同时请求这些资源。如果仅用一个连接,它需要发起请求、等待响应,之后才能发起下一次请求。HTTP1有一个称为“管道化”的特性,允许一次发送一组请求,但是只能按照发送顺序依次接收响应,并且由于该特性受多种因素影响,基本无实用价值。于是,在请求的过程中,如果出现某些情况导致剩下的所有工作都回被阻塞在那次请求应答之后,就导致了“队头阻塞”。它回阻塞网络传输和前端页面的渲染,直到失去响应。

2.TCP的利用低效

TCP协议是可靠传输的协议,其涉及的核心概念是拥塞窗口,它是指在接收方确认数据包前,发送方可以发出TCP包的数量。举个栗子,如果拥塞窗口为1,那么发送方发出1个数据包后,只有接收方确认了那个包,才能发送下一个。一般的,每次发送一个数据包的情况也并不是低效的。

TCP还有一个概念称为慢启动,它是用来探索当前连接对应拥塞窗口合适的大小。发送方在收到每个确认回复后额外可以发送一个未确认包。以此类推,如果收到了2个确认回复,则发出4个,呈倍数增加。这种发包数的增长回很快达到协议规定的上限,然后就进入拥塞避免阶段。在这种机制下,需要多次往返数据请求才能最终确认最佳的拥塞窗口大小,自然就增加了资源传输时间。

3.臃肿的首部

http1的消息首部无法压缩

4.优先级受限

浏览器为了请求优先级高的资源,回推迟请求其他资源。然而在优先级高的资源获取到之后,在处理它的过程中(比如渲染),浏览器并不会发起新的资源请求,那么就浪费了这段可以重新请求的空闲时间。

HTTP2的改变

针对上述的问题,人们在HTTP2中加入了新特性补足了HTTP1的短板。在2015年发布的大部分现代浏览器已经支持了HTTP2,并向下兼容HTTP1。另外补充一点,虽然HTTP2的规范并不明确要求TLS,也支持明文传输,但是在主流浏览器中都是不支持非TLS的HTTP2的。

分层的概念

HTTP2大致可以分为两层:分帧层,即HTTP2多路复用能力的核心部分;数据层,其中包含了HTTP1的内容。

HTTP的优势

  • 基于帧的二进制协议
  • 首部压缩
  • 多路复用
  • 服务器推送

二进制分帧

是HTTP的最小单位,消息由一个或多个帧组成。

是通信的虚拟通道,每个流都有唯一的一个ID。可以将其视为连接上的一系列帧,它们构成了单独的HTTP请求和响应。若客户端想发出请求,它会开启一个新的流。接着,服务端就在这个流上回复,数据是双向的。由于有多路复用的特性,多个请求和响应可以交错,不会造成阻塞。

多路复用和优先级

在HTTP1中可能会出现以下的问题:

  • 一次只能处理一个请求或响应,并且在完成之前不能停止解析
  • 无法预判解析需要多大的内存
    上述的问题可能会导致通信的阻塞。

    HTTP2的帧结构明确了资源的数量级,并且请求和响应可以交错甚至多路复用。

借助这一特性,网络通信的的性能就大大提升了:

  • 同个域名只需占用一个TCP连接
  • 单个连接上的请求和响应可以并行交错,互不干扰

并且HTTP2规定每个请求都可以带有一个优先级值,数值越大优先级越高。这样通信双方就可以按最优的条件传输资源了。

服务器推送

在HTTP2规范中,服务端可以主动向客户端发送资源,并且,客户端也可以选择是否接收。

关于丢包

丢包是HTTP2的命门,频繁丢包会影响HTTP2的页面传输,主要是因为HTTP2开启了单一TCP连接,每次有丢包时,TCP拥塞窗口就会缩减。



参考:

  • 《HTTP/2基础教程》

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant