一文搞定HTTP和HTTPS,巩固你的HTTP知识体系

640次阅读  |  发布于3年以前

http 是我们几乎天天都要打交道的东西,相关知识点有点多,所以也有不少面试必问的点,这里做了一些整理,帮且大家树立完整的 http 知识体系,对面试官说 so easy

篇幅过长就列了个大纲,方便查找

大纲

HTTP 的特点和缺点

特点无连接无状态灵活简单快速

缺点无状态不安全明文传输队头阻塞

HTTP 报文组成部分

http报文:由请求报文响应报文组成

请求报文:由请求行请求头空行请求体四部分组成

响应报文:由状态行响应头空行响应体四部分组成

HTTP 请求方法(9种)

HTTP1.0: GETPOSTHEAD

HTTP1.1: PUTPATCHDELETEOPTIONSTRACECONNECT

方法 描述
GET 获取资源
POST 传输资源,通常会造成服务器资源的修改
HEAD 获得报文首部
PUT 更新资源
PATCH 对PUT的补充,对已知资源部分更新 菜鸟
DELETE 删除资源
OPTIONS 列出请求资源支持的请求方法,用来跨域请求
TRACE 追踪请求/响应路径,用于测试或诊断
CONNECT 将连接改为管道方式用于代理服务器(隧道代理下面有讲)

GET 和 POST 的区别

常见 HTTP 状态码

1xx: 指示信息——表示请求已接收,继续处理

2xx: 成功——表示请求已被成功接收

3xx: 重定向——表示要完成请求必须进行进一步操作

4xx: 客户端错误——表示请求有语法错误或请求无法实现

5xx: 服务端错误——表示服务器未能实现合法的请求

常见状态码:

状态码 描述
200 请求成功
206 已完成指定范围的请求(带Range头的GET请求),场景如video,audio播放文件较大,文件分片时
301 永久重定向
302 临时重定向
304 请求资源未修改,可以使用缓存的资源,不用在服务器取
400 请求有语法错误
401 没有权限访问
403 服务器拒绝执行请求,场景如不允许直接访问,只能通过服务器访问时
404 请求资源不存在
500 服务器内部错误,无法完成请求
503 请求未完成,因服务器过载、宕机或维护等

什么是持久连接/长连接

http1.0协议采用的是"请求-应答"模式,当使用普通模式,每个请求/应答客户与服务器都要新建一个连接,完成之后立即断开连接(http协议为无连接的协议)

http1.1版本支持长连接,即请求头添加Connection: Keep-Alive,使用Keep-Alive模式(又称持久连接,连接复用)建立一个TCP连接后使客户端到服务端的连接持续有效,可以发送/接受多个http请求/响应,当出现对服务器的后续请求时,Keep-Alive功能避免了建立或者重新建立连接

如图:短连接极大的降低了传输效率

长连接优缺点

优点

缺点

一个长连接建立后,如果一直保持连接,对服务器来说是多么的浪费资源呀,而且长连接时间的长短,直接影响到服务器的并发数

还有就是可能造成队头堵塞(下面有讲),造成信息延迟

如何避免长连接资源浪费?

什么是管线化(管道化)

http1.1在使用长连接的情况下,建立一个连接通道后,连接上消息的传递类似于

请求1 -> 响应1 -> 请求2 -> 响应2 -> 请求3 -> 响应3

管理化连接的消息就变成了类似这样

请求1 -> 请求2 -> 请求3 -> 响应1 -> 响应2 -> 响应3

管线化是在同一个TCP连接里发一个请求后不必等其回来就可以继续发请求出去,这可以减少整体的响应时间,但是服务器还是会按照请求的顺序响应请求,所以如果有许多请求,而前面的请求响应很慢,就产生一个著名的问题队头堵塞(下面有讲解决方法)

管线化的特点:

如何解决 HTTP 的队头阻塞问题

http1.0协议采用的是请求-应答模式,报文必须是一发一收,就形成了一个先进先出的串行队列,没有轻重缓急的优先级,只有入队的先后顺序,排在最前面的请求最先处理,就导致如果队首的请求耗时过长,后面的请求就只能处于阻塞状态,这就是著名的队头阻塞问题。解决如下:

并发连接

因为一个域名允许分配多个长连接,就相当于增加了任务队列,不至于一个队列里的任务阻塞了其他全部任务。以前在RFC2616中规定过客户端最多只能并发2个连接,但是现实是很多浏览器不按套路出牌,就是遵守这个标准T_T,所以在RFC7230把这个规定取消掉了,现在的浏览器标准中一个域名并发连接可以有6~8个,记住是6~8个,不是6个(Chrome6个/Firefox8个)

如果这个还不能满足你

继续,不要停...

域名分片

一个域名最多可以并发6~8个,那咱就多来几个域名

比如a.baidu.com,b.baidu.com,c.baidu.com,多准备几个二级域名,当我们访问baidu.com时,可以让不同的资源从不同的二域名中获取,而它们都指向同一台服务器,这样能够并发更多的长连接了

而在HTTP2.0下,可以一瞬间加载出来很多资源,因为支持多路复用,可以在一个TCP连接中发送多个请求

说一下 HTTP 代理

常见的代理有两种:普通代理(中间人代理)隧道代理

普通代理(中间人代理)

如图:代理服务器相当于一个中间人,一直帮两边传递东西,好可怜~~

不过它可以在中间可以帮我们过滤、缓存、负载均衡(多台服务器共用一台代理情况下)等一些处理

注意,实际场景中客户端和服务器之间可能有多个代理服务器

隧道代理

客户端通过CONNECT方法请求隧道代理创建一个可以到任意目标服务器和端口号的TCP连接,创建成功之后隧道代理只做请求和响应数据的转发,中间它不会做任何处理

为什么需要隧道代理呢?

我们都知道https服务是需要网站有证书的,而代理服务器显然没有,所以浏览器和代理之间无法创建TLS,所以就有了隧道代理,它把浏览器的数据原样透传,这样就实现了通过中间代理和服务端进行TLS握手,然后进行加密传输

可能有人会问,那还要代理干嘛,直接请求服务器不是更好吗

代理服务器,到底有什么好处呢?

代理最常见的请求头

Via

是一个能用首部,由代理服务器添加,适用于正向和反向代理,在请求和响应首部均可出现,这个消息首部可以用来追踪消息转发情况,防止循环请求,还可以识别在请求或响应传递链中消息发送者对于协议的支持能力,详情请看MDN

Via: 1.1 vegur
Via: HTTP/1.1 GWA
Via: 1.0 fred, 1.1 p.example.net

X-Forwarded-For

记录客户端请求的来源IP,每经过一级代理(匿名代理除外),代理服务器都会把这次请求的来源IP追加进去

X-Forwarded-For: client,proxy1,proxy2

注意:与服务器直连的代理服务器的IP不会被追加进去,该代理可能过TCP连接的Remote Address字段获取到与服务器直连的代理服务器IP

X-Real-IP

一般记录真实发出请求的客户端的IP,还有X-Forwarded-HostX-Forwarded-Proto分别记录真实发出请求的客户端的域名协议名

代理中客户端IP伪造问题以及如何预防?

X-Forwarded-For是可以伪造的,比如一些通过X-Forwarded-For获取到客户端IP来限制刷票的系统就可以通过伪造该请求头达到刷票的目的,如果客户端请求显示指定了

X-Forwarded-For:192.168.1.108

那么服务端收到的这个请求头,第一个IP就是伪造的

预防

1 . 在对外Nginx服务器上配置

location / {
 proxy_set_header X-Forwarded-For $remote_addr
}

这样第一个IP就是从TCP连接客户端的IP,不会读取伪造的

2 . 从右到左遍历X-Forwarded-For的IP,排除已知代理服务器IP和内网IP,获取到第一个符合条件的IP就可以了

正向代理和反向代理

正向代理

工作在客户端的代理为正向代理。使用正向代理的时候,需要在客户端配置需要使用的代理服务器,正向代理对服务端透明。比如抓包工具Fiddler、Charles以及访问一些外网网站的代理工具都是正向代理

正向代理通常用于

反向代理

工作在服务端的代理称为反向代理。使用反向代理的时候,不需要在客户端进行设置,反向代理对客户端透明。如Nginx就是反向代理

反向代理通常用于负载均衡服务端缓存流量隔离日志金丝雀发布

代理中的长连接

在各个代理和服务器、客户端节点之间是一段一段的TCP连接,客户端通过代理访问目标服务器也叫逐段传输,用于逐段传输的请求头叫逐段传输头

逐段传输头会在每一段传输的中间代理中处理掉,不会传给下一个代理

标准的逐段传输头有:Keep-AliveTransfer-EncodingTEConnectionTrailerUpgradeProxy-AuthorizationProxy-Authenticate

Connection头决定当前事务完成后是否关闭连接,如果该值为keep-alive,则连接是持久连接不会关闭,使得对同一服务器的请求可以继续在该连接上完成

说一下 HTTP 缓存及缓存代理

关于http缓存在上一篇文章里有了详细介绍 (建议收藏)为什么第二次打开页面快?五步吃透前端缓存,让页面飞起

缓存代理就是让代理服务器接管一部分的服务端的http缓存,客户端缓存过期之后就近到代理服务器的缓存中获取,代理缓存过期了才请求源服务器,这样流量大的时候能明显降低源服务器的压力

注意响应头字段

HTTPS

HTTPS 是超文本传输安全协议,即HTTP + SSL/TLS。说白了,就是一个加强版的HTTP

HTTP本文开始讲了,所以我们要理解HTTPS的精华,就要先弄清楚这个SSL/TLS

SSL/TLS

一张图让你理解SSL和TLS的关系

如图,TLS是SSL的升级版,而且TLS1.2版本以下都已废弃,目前主要用的是TLS 1.2TLS 1.3。而OpenSSL则是开源版本

那么它到底是个啥呢?

浏览器和服务器通信之前会先协商,选出它们都支持的加密套件,用来实现安全的通信。常见加密套件

随便拿出一个加密套件举例,如:RSA-PSK-AES128-GCM-SHA256,就是长这样,代表什么意思呢,我们看图

为什么需要用到这么多算法呢?

为了保证安全,TLS需要保证信息的:机密性可用性完整性认证性不可否认性,每一种算法都有其特定的用处

HTTPS 中 TLS 的加密算法

为什么说https是安全的? https一定是安全的吗?(考察https中间人劫持,我另一篇有关于详细介绍网络安全) 有什么解决办法? https的证书校验过程是怎么样的? 证书校验用到了哪些算法?

对称加密算法

就是加密和解密使用同一个密钥。如AES、DES。加解密过程:

  1. 浏览器给服务器发送一个随机数client-random和一个支持的加密方法列表
  2. 服务器给浏览器返回另一个随机数server-random和双方都支持的加密方法
  3. 然后两者用加密方法将两个随机数混合生成密钥,这就是通信双上加解密的密钥

问题是双方如何安全的传递两个随机数和加密方法,直接传给客户端,那过程中就很可能被窃取,别人就能成功解密拿到数据,往下看

不对称加密算法

就是一对密钥,有公钥(public key)和私钥(private key),其中一个密钥加密后的数据,只能让另一个密钥进行解密。如RSAECDHE。加解密过程:

  1. 浏览器给服务器发送一个随机数client-random和一个支持的加密方法列表
  2. 服务器把另一个随机数server-random加密方法公钥传给浏览器
  3. 然后浏览器用公钥将两个随机数加密,生成密钥,这个密钥只能用私钥解密

使用公钥反推出私钥是非常困难,但不是做不到,随着计算机运算能力提高,非对称密钥至少要2048位才能保证安全性,这就导致性能上要比对称加密要差很多

所以!

TLS实际用的是两种算法的混合加密通过 非对称加密算法 交换 对称加密算法 的密钥,交换完成后,再使用对称加密进行加解密传输数据。这样就保证了会话的机密性。过程如下

  1. 浏览器给服务器发送一个随机数client-random和一个支持的加密方法列表
  2. 服务器把另一个随机数server-random加密方法公钥传给浏览器
  3. 浏览器又生成另一个随机数pre-random,并用公钥加密后传给服务器
  4. 服务器再用私钥解密,得到pre-random
  5. 浏览器和服务器都将三个随机数用加密方法混合生成最终密钥

这样即便被截持,中间人没有私钥就拿不到pre-random,就无法生成最终密钥。

可又有问题来了,如果一开始就被DNS截持,我们拿到的公钥是中间人的,而不是服务器的,数据还是会被窃取,所以数字证书来了,往下看,先简单说一下摘要算法

摘要算法

主要用于保证信息的完整性。常见的MD5算法散列函数哈希函数都属于这类算法,其特点就是单向性无法反推原文

假如信息被截取,并重新生成了摘要,这时候就判断不出来是否被篡改了,所以需要给摘要也通过会话密钥进行加密,这样就看不到明文信息,保证了安全性,同时也保证了完整性

如何保证数据不被篡改?签名原理和证书?

数字证书(数字签名)

它可以帮我们验证服务器身份。因为如果没有验证的话,就可能被中间人劫持,假如请求被中间人截获,中间人把他自己的公钥给了客户端,客户端收到公钥就把信息发给中间人了,中间人解密拿到数据后,再请求实际服务器,拿到服务器公钥,再把信息发给服务器

这样不知不觉间信息就被人窃取了,所以在结合对称和非对称加密的基础上,又添加了数字证书认证的步骤,让服务器证明自己的身份

数字证书需要向有权威的认证机构(CA)获取授权给服务器。首先,服务器CA机构分别有一对密钥(公钥和私钥),然后是如何生成数字证书的呢?

服务器配置好证书,以后客户端连接服务器,都先把证书发给客户端验证并获取服务器的公钥。

证书验证流程

证书认证又分为单向认证双向认证

单向认证:服务器发送证书,客户端验证证书 双向认证:服务器和客户端分别提供证书给对方,并互相验证对方的证书

不过大多数https服务器都是单向认证,如果服务器需要验证客户端的身份,一般通过用户名、密码、手机验证码等之类的凭证来验证。只有更高级别的要求的系统,比如大额网银转账等,就会提供双向认证的场景,来确保对客户身份提供认证性

HTTPS 连接过程和优化

我们知道了https就只是比http多了一步TLS连接

TLS连接是怎么回事呢,根据TLS版本和密钥交换法不同,过程也不一样,有三种方式

RSA握手

早期的TLS密钥交换法都是使用RSA算法,它的握手流程是这样子的

  1. 浏览器给服务器发送一个随机数client-random和一个支持的加密方法列表
  2. 服务器把另一个随机数server-random加密方法公钥传给浏览器
  3. 浏览器又生成另一个随机数pre-random,并用公钥加密后传给服务器
  4. 服务器再用私钥解密,得到pre-random,此时浏览器和服务器都得到三个随机数了,各自将三个随机数用加密方法混合生成最终密钥

然后开始通信

TLS 1.2 版

TLS 1.2版的用的是ECDHE密钥交换法,看图

  1. 浏览器给服务器发送一个随机数client-random、TLS版本和一个支持的加密方法列表
  2. 服务器生成一个椭圆曲线参数server-params、随机数server-random加密方法证书等传给浏览器
  3. 浏览器又生成椭圆曲线参数client-params,握手数据摘要等信息传给服务器
  4. 服务器再返回摘要给浏览器确认应答

这个版本不再生成椭圆曲线参数cliend-paramsserver-params,而是在服务器和浏览器两边都得到server-paramsclient-params之后,就用ECDHE算法直接算出pre-random,这就两边都有了三个随机数,然后各自再将三个随机加密混合生成最终密钥

TLS 1.3版

在TLS1.3版本中废弃了RSA算法,因为RSA算法可能泄露私钥导致历史报文全部被破解,而ECDHE算法每次握手都会生成临时的密钥,所以就算私钥被破解,也只能破解一条报文,而不会对之前的历史信息产生影响,,所以在TLS 1.3中彻底取代了RSA。目前主流都是用ECDHE算法来做密钥交换的

TLS1.3版本中握手过程是这样子的

  1. 浏览器生成client-params、和client-random、TLS版本和加密方法列表发送给服务器
  2. 服务器返回server-paramsserver-random加密方法证书摘要等传给浏览器
  3. 浏览器确认应答,返回握手数据摘要等信息传给服务器

简单说就是简化了握手过程,只有三步,把原来的两个RTT打包成一个发送了,所以减少了传输次数。这种握手方式也叫1-RTT握手

这种握手方还有优化空间吗?

有的,用会话复用

会话复用

会话复用有两种方式:Session IDSession Ticket

Session ID:就是客户端和服务器首次连接手各自保存会话ID,并存储会话密钥,下次再连接时,客户端发送ID过来,服务器这边再查找ID,如果找到了就直接复用会话,密钥也不用重新生成

可是这样的话,在客户端数量庞大的时候,对服务器的存储压力可就大了

所以出来了第二种方式 Session Ticket:就是双方连接成功后服务器加密会话信息,用Session Ticket消息发给客户端存储起来,下次再连接时就把这个Session Ticket解密,验证有没有过期,如果没有过期就复用会话。原理就是把存储压力分给客户端。

这样就万无一失了吗?

No,这样也存在安全问题。因为每次要用一个固定的密钥来解密Session Ticket,一旦密钥被窃取,那所有历史记录也就被破解了,所以只能尽量避免这种问题定期更换密钥。毕竟节省了不少生成会话密钥和这些算法的耗时,性能还是提升了嘛

那刚说了1-RTT,那能不能优化到0-RTT

还真可以,做法就是发送Session Ticket的时候带上应用数据,不用等服务端确认。这种方式被称为PSK(Pre-Shared Key)

这样万无一失了吗?

尴了个尬,还是不行。这PSK要是被窃取,人家不断向服务器重发,就直接增加了服务器被攻击的风险

虽然不是绝对安全,但是现行架构下最安全的解决文案了,大大增加了中间人的攻击成本

HTTPS优缺点

优点

缺点

HTTP 和 HTTPS 的区别

HTTPS 的性能优化

访问速度优化

  1. 会话复用,上面说了,复用session可以减少 CPU 消耗,因为不需要进行非对称密钥交换的计算。可以提升访问速度,不需要进行完全握手阶段二,节省了一个 RTT 和计算耗时。
  2. 使用 SPDY 或者 HTTP2。SPDY 最大的特性就是多路复用,能将多个 HTTP 请求在同一个连接上一起发出去,不像目前的 HTTP 协议一样,只能串行地逐个发送请求。Pipeline 虽然支持多个请求一起发送,但是接收时依然得按照顺序接收,本质上无法解决并发的问题。HTTP2支持多路复用,有同样的效果。
  3. 设置HSTS,服务端返回一个 HSTS 的 http header,浏览器获取到 HSTS 头部之后,在一段时间内,不管用户输入www.baidu.com还是http:\/\/www.baidu.com ,都会默认将请求内部跳转成https:\/\/www.baidu.com。Chrome, firefox, ie 都支持了 HSTS。
  4. Nginx设置Ocsp stapling。Ocsp 全称在线证书状态检查协议 (rfc6960),用来向 CA 站点查询证书状态,比如是否撤销。通常情况下,浏览器使用 OCSP 协议发起查询请求,CA 返回证书状态内容,然后浏览器接受证书是否可信的状态。这个过程非常消耗时间,因为 CA 站点有可能在国外,网络不稳定,RTT 也比较大。如果不需要查询则可节约时间。
  5. False start。简单概括 False start 的原理就是在 clientkeyexchange 发出时将应用层数据一起发出来,能够节省一个 RTT。

计算性能优化

  1. 优先使用 ECC椭圆加密算术
  2. 使用最新版的 OpenSSL
  3. TLS 远程代理计算
  4. 硬件加速方案

HTTP 版本

1991年HTTP 0.9版,只有一个GET,而且只支持纯文本内容,早已过时就不讲了

HTTP 1.0(1996年)

HTTP 1.1(1997年)

缺点:主要是连接缓慢,服务器只能按顺序响应,如果某个请求花了很长时间,就会出现请求队头阻塞

虽然出了很多优化技巧:为了增加并发请求,做域名拆分、资源合并、精灵图、资源预取...等等

最终为了推进从协议上进行优化,Google跳出来,推出SPDY协议

SPDY(2009年)

SPDY(读作“SPeeDY”)是Google开发的基于TCP的会话层协议

主要通过帧、多路复用、请求优先级、HTTP报头压缩、服务器推送以最小化网络延迟,提升网络速度,优化用户的网络使用体验

原理是在SSL层上增加一个SPDY会话层,以在一个TCP连接中实现并发流。通常的HTTP GET和POST格式仍然是一样的,然而SPDY为编码和传输数据设计了一个新的帧格式。因为流是双向的,所以可以在客户端和服务端启动

虽然诞生后很快被所有主流浏览器所采用,并且服务器和代理也提供了支持,但是SPDY核心人员后来都参加到HTTP 2.0开发中去了,自HTTP2.0开发完成就不再支持SPDY协议了,并在Chrome 51中删掉了SPDY的支持

HTTP 2.0(2015年)

说出http2中至少三个新特性?

缺点

SPDY 和 HTTP2 的区别

HTTP1 和 HTTP2

HTTP 3.0/QUIC

由于HTTP 2.0依赖于TCP,TCP有什么问题那HTTP2就会有什么问题。最主要的还是队头阻塞,在应用层的问题解决了,可是在TCP协议层的队头阻塞还没有解决。

TCP在丢包的时候会进行重传,前面有一个包没收到,就只能把后面的包放到缓冲区,应用层是无法取数据的,也就是说HTTP2的多路复用并行性对于TCP的丢失恢复机制不管用,因此丢失或重新排序的数据都会导致交互挂掉

为了解决这个问题,Google又发明了QUIC协议

并在2018年11月将QUIC正式改名为HTTP 3.0

特点

结语

点赞支持、手留余香、与有荣焉

感谢你能看到这里,加油哦!

参考

HTTPS:网络安全攻坚战

HTTP灵魂之问,巩固你的 HTTP 知识体系

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8