文章目录
http 概述
摘自维基百科:
超文本传输协议(英语:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议[1]。HTTP是万维网的数据通信的基础。
设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。通过HTTP或者HTTPS协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。
HTTP的版本更迭
版本更迭究竟在更迭什么?
影响一个 HTTP 网络请求的因素主要有两个:带宽和延迟。
-
带宽:如果说我们还停留在拨号上网的阶段,带宽可能会成为一个比较严重影响请求的问题,但是现在网络基础建设已经使得带宽得到极大的提升,我们不再会担心由带宽而影响网速,那么就只剩下延迟了。
-
延迟:
-
浏览器阻塞(HOL blocking):浏览器会因为一些原因阻塞请求。浏览器对于同一个域名,同时只能有 4 个连接(这个根据浏览器内核不同可能会有所差异),超过浏览器最大连接数限制,后续请求就会被阻塞。
-
DNS 查询(这个已经基本解决)(DNS Lookup):浏览器需要知道目标服务器的 IP 才能建立连接。将域名解析为 IP 的这个系统就是 DNS。这个通常可以利用DNS缓存结果来达到减少这个时间的目的。
-
复用连接(Initial connection):HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文,达到真正的建立连接,但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。
-
http0.9
已过时。只接受GET一种请求方法,没有在通讯中指定版本号,且不支持请求头。由于该版本不支持POST方法,因此客户端无法向服务器传递太多信息。
http1.0
主要缺点:
- 短连接:如果 HTML 中包含 src 图片URL。就会是新的一次 http 连接。耗时又耗力,同时也会导致无法建立太多连接( http 的连接对应于域名而言)。
- head of line blocking(队头阻塞问题):http 1.0的请求顺序是:
在第一个请求没有收到回复之前,后续从应用层发出的请求只能排队,请求2,3,4,5只能等请求1的response回来之后才能逐个发出
http1.1
对应与 http1.0 的改进:
- 连接复用: 默认 Keep-Alive
- 管线化处理请求:
一次性发送多个request请求。然而 pipelining 在接收response返回时,也必须依顺序接收
,如果前一个请求遇到了阻塞,后面的请求即使已经处理完毕了,仍然需要等待阻塞的请求处理完毕。这也就是队头阻塞(Head of line blocking)。
管线化的原因就是:
我们传输的request和response都是基本于文本的,这样就会引发一个问题:所有的数据必须按顺序传输,比如需要传输:hello world,只能从h到d一个一个的传输,不能并行传输,因为接收端并不知道这些字符的顺序,所以并行传输在HTTP1.1是不能实现的。
- 更多缓存:
- Range 域:只请求一部分资源
- Host 域:随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。用 Host 域来标明哪个主机。
还存在的缺点 :
- 队头阻塞(Head of line blocking)的问题。
http2
对应与http1.1的改进:
- 多路复用 (Multiplexing): 复用同一个连接(同一域名不管访问多少文件,也只建立一路连接)。
- 二进制分帧:在 应用层(HTTP/2)和传输层(TCP or UDP)之间增加一个二进制分帧层。
- 用以
支持多种格式文件,且提高解析效率
。其实就和PB等差不多。
- 用以
-
帧:HTTP/2 数据通信的最小单位消息:指 HTTP/2 中逻辑上的 HTTP 消息。例如请求和响应等,消息由一个或多个帧组成。
-
流:存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一的整数ID。
HTTP/2 采用二进制格式传输数据,而非 HTTP 1.x 的文本格式,二进制协议解析起来更高效。 HTTP / 1 的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。
HTTP/2 中,同域名下所有通信都在单个连接上完成,该连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装。
- 首部压缩(Header Compression):HTTP/2 则使用了专门为首部压缩而设计的 HPACK 算法。
- 服务端推送(Server Push):如果一个请求是由你的主页发起的,服务器很可能会响应主页内容、logo 以及样式表,因为它知道客户端会用到这些东西。这相当于在一个 HTML 文档内集合了所有的资源,不过与之相比,服务器推送还有一个很大的优势:可以缓存!也让在遵循同源的情况下,不同页面之间可以共享缓存资源成为可能。
所以 http2.0发送请求是这样的:
图汇总:
加餐:为啥有了keep-alive还需要多路复用呐 ?
-
Keep-Alive解决的问题
Keep-Alive解决的核心问题:一定时间内,同一域名多次请求数据,只建立一次HTTP请求,其他请求可复用每一次建立的连接通道,以达到提高请求效率的问题。这里面所说的一定时间是可以配置的,不管你用的是Apache还是nginx。 -
HTTP1.1还是存在效率问题
如上面所说,在HTTP1.1中是默认开启了Keep-Alive,他解决了多次连接的问题,但是依然有两个效率上的问题:- 第一个:串行的文件传输。当请求a文件时,b文件只能等待,等待a连接到服务器、服务器处理文件、服务器返回文件,这三个步骤。我们假设这三步用时都是1秒,那么a文件用时为3秒,b文件传输完成用时为6秒,依此类推。(注:此项计算有一个前提条件,就是浏览器和服务器是单通道传输)
- 第二个:连接数过多。我们假设Apache设置了最大并发数为300,因为浏览器限制,浏览器发起的最大请求数为6,也就是服务器能承载的最高并发为50,当第51个人访问时,就需要等待前面某个请求处理完成。
HTTP 的下一任 HTTPS
基础概念入门
1. 消息摘要-Message Digest
消息摘要(Message Digest),又称数字摘要(Digital Digest)或数字指纹(Finger Print)。简单来说, 消息摘要就是在消息数据上,执行一个单向的Hash函数,生成一个固定长度的Hash值,这个Hash值即是消息摘要。
其中执行的Hash函数就是所谓的消息摘要算法。主要有如下特性:
输出结果是定长的。
如:MD5->128Bit,区块链以及 Https 使用的SHA256算法->256Bit。相同的输入一定对应相同的输出。
消息摘要函数是单向的。
无法根据消息摘要的结果去推算出原始数据。- 存在“碰撞”。好的摘要算法,没有人能从中找到“碰撞”,虽然“碰撞”是肯定存在的(由于长明文生成短摘要的Hash必然会产生碰撞)。即对于给定的一个摘要,不可能找到一条信息使其摘要正好是给定的。或 者说,
无法找到两条消息,使它们的摘要相同。
2. 数字签名
数字签名,就是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。
使用了公钥加密领域的技术实现,一套数字签名通常定义两种互补的运算,一个用于签名
,另一个用于验证
。
什么是对称加密和非对称加密?
- 对称加密:
密钥相同
,性能很好。 - 非对称加密:
公钥分发,私钥保密。公私钥互相解加密
。在实际的使用中,有需要的人会生成一对公钥和私钥, 把公钥发布出去给别人使用,自己保留私钥。目前使用最广泛的公钥密码体制是RSA密码体制。
非对称加密的第二种用途:身份验证
私钥加密的数据,只有使用对应人分发的公钥才能解密。从而可以唯一确定发送人信息。并且不能否认他曾经发布过该消息
数字签名的来源
如果按照上面的方案去做,当需要发送的数据非常庞大时,加密解密过程就会变得极其低效。这也是此方案一直没有盛行的主要原因。那么如何改进呐?答:先用摘要算法,再用签名。
真正被使用的数字签名
几乎所有的数字签名方案都要和快速高效的摘要算法(Hash函数)一起使用,当公钥算法与摘要算法结合 起来使用时,便构成了一种有效地数字签名方案。
那么过程便是:
用摘要算法对消息进行摘要
。再把摘要值用发送者的私钥加密
。
最后的结果就是所谓的数字签名。发送者需要将原始信息和数字签名一同发送给接收者。而接收者在接收到原始信息和数字签名后,通过以下3步验证消息的真伪:
先把接收到的原始消息用同样的摘要算法摘要,形成“准签体”
。对附加上的那段数字签名,使用预先得到的公钥解密
。比较前两步所得到的两段消息是否一致。如果一致,则表明消息确实是期望的发送者发的,且内容没有被篡改过;相反,如果不一致,则表明传送的过程中一定出了问题,消息不可信
。
所以 数字签名就是 非对称 + 消息摘要
那么存在什么问题呐?
通过数字签名技术,确实可以解决可靠通信的问题。一旦验签通过,接收者就能确信该消息是期望的发送者发送的,而发送者也不能否认曾经发送过该消息。不过前面提到的数字签名方法,有一个前提,就是消息的接收者必须事先得到正确的公钥。如果一开始公钥就被别人篡改了,那坏人就会被你当成好人,而真正的消息发送者给你发的消息会被你视作无效的。
而且,很多时候根本就不具备事先沟通公钥的信息通道。那么如何保证公钥的安全可信呢?这就要靠数字证书来解决了。
举例:原先是苏珊与鲍勃通信。鲍勃拥有私钥,苏珊拥有公钥。
复杂的情况出现了。道格想欺骗苏珊,他偷偷使用了苏珊的电脑,用自己的公钥换走了鲍勃的公钥。此时,苏珊实际拥有的是道格的公钥,但是还以为这是鲍勃的公钥。因此,道格就可以冒充鲍勃,用自己的私钥做成"数字签名",写信给苏珊,让苏珊用假的鲍勃公钥进行解密。
而苏珊却会将真正来自鲍勃的信息丢弃。
3. 数字证书
数字证书是一个经证书授权(Certificate Authentication)中心数字签名的包含公钥拥有者信息以及公钥的文件
。数字证书的格式普遍采用的是X.509V3国际标准,一个标准的X.509数字证书通常包含以下内容:
- 证书的发布机构(Issuer) - 该证书是由哪个机构(CA中心)颁发的。
- 证书的有效期(Validity) - 证书的有效期,或者说使用期限。过了该日期,证书就失效了。
- 证书所有人的公钥(Public-Key) - 该证书所有人想要公布出去的公钥。
- 证书所有人的名称(Subject) - 这个证书是发给谁的,或者说证书的所有者,一般是某个人或者某个公 司名称、机构的名称、公司网站的网址等。
- 证书所使用的签名算法(Signature algorithm) - 这个数字证书的数字签名所使用的加密算法,这样就 可以使用证书发布机构的证书里面的公钥,根据这个算法对指纹进行解密。
- 证书发行者对证书的数字签名(Thumbprint) - 也就是该数字证书的指纹,用于保证数字证书的完整 性,确保证书没有被修改过。其原理就是在发布证书时,CA机构会根据签名算法(Signature algorithm)对整个证书计算其hash值(指纹)并和证书放在一起,使用者打开证书时,自己也根据签名 算法计算一下证书的hash值(指纹),如果和证书中记录的指纹对的上,就说明证书没有被修改过。
后来,苏珊感觉不对劲,发现自己无法确定公钥是否真的属于鲍勃。她想到了一个办法,要求鲍勃去找"证书中心"(certificate authority,简称CA),为公钥做认证。证书中心用自己的私钥,对鲍勃的公钥和一些相关信息一起加密,生成"数字证书"(Digital Certificate)
。
鲍勃拿到数字证书以后,就可以放心了。以后再给苏珊写信,只要在签名的同时,再附上数字证书就行了。
苏珊收信后,用CA的公钥解开数字证书,就可以拿到鲍勃真实的公钥了,然后就能证明"数字签名"是否真的是鲍勃签的。
OK。。。那你就先这样理解吧就。
一般而言,证书的下发是这个样子的:
那么在TLS握手时,当服务器下发公钥证书链的时候,浏览器就会去 OCSP 响应程序查这些证书是否过期。假如没有过期,就使用对应 CA 机构的公钥进行证书的解密。得到服务器的公钥。然后就是上边所说的数字签名的流程了!!!
http的缺陷
- 明文传输
- 不验证通信方的身份,因此有可能遭遇伪装;
- 信息会被篡改
从 SSL -> TLS协议
知道了TLS的加密套件。我们正式来看看 TLS 的完整握手通讯流程。
最后就是使用生成的密钥进行加密通讯。
注意 TLS 握手流程中存在两对公私钥,一个是CA的公私钥对(校验服务器证书合法性),一个我们自己生成的公私钥对(用于协商秘钥)。
未来前景
看谷歌。
拓展阅读:
参考:数字签名是什么?