HTTP常见面试问题

HTTP基本概念

HTTP是什么

HTTP全称为超文本传输协议(HyperText Transfer Protocol)。

  1. 超文本

    如HTTP名字中所说的,其传输的是超文本,超文本从字面上理解是超过了普通的文本文字,也就是还包括文字以外的内容,如图片、视频、超链接等,超文本 就是这些内容的混合体。

    HTML(Hyper Text Markup Language)就是最常见的超文本了,它本身只是纯文字的文件,但是内部用很多标签定义了图片、视频的链接,经过浏览器解释之后,呈现给我们的就是一个有文字、有图片和视频的网页了。

  2. 传输

    所谓“传输”,就是将东西从一个地方搬到另一个地方。

    HTTP协议是一个双向协议。

    我们上网的时候,浏览器是请求方A,访问的网站就是应答方B,双方约定使用HTTP协议来通信,于是浏览器把请求数据发送给网站,网站再把一些数据返回给浏览器,最后由浏览器渲染出来显示在屏幕上。

HTTP常见面试问题_第1张图片

虽然数据是在A点和B点传输,但是中间也允许有中转或接力。

这就好比传纸条,第一排的同学传到最后面一排的同学,传递的过程中就要经过好多同学(中间人),而在HTTP里,需要中间人遵从HTTP协议,只要不打扰基本的数据传输,就可以任意添加额外的东西。

  1. 协议

    我们生活中的协议,本质上和计算机中的协议是相同的,协议的特点:

    • 协:代表需要有两个及以上的参与者。例如:三方协议里的参与者包括(你、公司、学校);租房协议里面包括(你和房东)。
    • 议:代表是对参与者的一种行为约定和规范。例如三方协议里规定试用期期限、毁约金等;租房协议里规定租期期限,每月租金金额、违约如何处理等。

    针对HTTP协议,我们可以这么理解,HTTP就是一个用在计算机世界里的协议,他是用计算机能够理解的语言建立了一种计算机之间交流通信的规范,以及相关的各种控制和错误处理方式(行为约定和规范)。

所以,总结以上说的三点,“超文本传输协议”就可以表述为:HTTP是一个用在计算机世界里专门在两点之间传输文字、图片、视频、音频等超文本数据的约定和规范。

那 HTTP是用于从互联网服务器传输到本地浏览器的协议,这种说法正确吗?

这种说法并不完全正确,也可以是从服务器传输到服务器的协议,所以用两点之间更加的准确。

HTTP常见的状态码有哪些

HTTP常见面试问题_第2张图片

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这类状态码表示客户端发送的报文有误,服务器无法处理。

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

5XX这类状态码表示客户端请求报文没问题,但是服务器处理时内部发生了错误,属于服务器端的错误码

  • 500 Internal Service Error和400类型相似,是一个笼统通用的错误码,服务器端发生的具体错误并没有提示出来。
  • 501 Not Implemented表示客户端请求的功能还不支持,类似于“即将业务,敬请期待”的意思。
  • 502 Bad Gateway通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。
  • 503 Service Unavailable表示服务器当前很忙,无法响应客户端,类似于“网络正忙,请稍后重试”。

HTTP常见的字段

  1. Host字段

    客户端发请求时用来指定服务器的域名

    Host: www.baidu.com
    
  2. Content-Length字段

    服务器返回数据时,会带有该字段,表名本次回应数据的长度。

    Content-Length: 1000
    

    如上就是告诉浏览器,本次服务器回应的数据长度是1000个字节,后面的字节就属于下一个回应了。

  3. Connection字段

    该字段最常用于客户端要求服务器使用TCP持久连接,以便其他请求复用。

    HTTP/1.1版本的默认连接都是持久连接,但是为了兼容老版本的HTTP,需要指定Connection首部字段的值为Keep-Alive

    Connection: keep-alive
    
  4. Content-Type字段

    该字段用于服务器回应时告诉客户端,本次数据是什么格式。

HTTP常见面试问题_第3张图片

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

上面的类型表名发送的是网页,而且编码是UTF-8。

客户端请求的时候可以试用Accept字段声明自己可以接受那些数据格式。

Accept: */*

上面代码中,客户端声明自己可以接受任何格式的数据。

  1. Content-Encoding 字段

    该字段说明了数据的压缩方法,表名服务器返回的数据使用了上面压缩格式。

HTTP常见面试问题_第4张图片

Content-Encoding: gzip

上面表示服务器返回的数据采用了gzip的压缩方式,告知客户端需要用此方法来解压数据。

Content-Type类似,客户端在请求时,可以用Accept-Encoding来说明自己可以接受那些压缩方法。

Accept-Encoding: gzip, deflate

GET和POST

GET和POST的区别

  • GET

    根据RFC规范,GET的语义是从服务器获取指定的资源,这个资源可以是静态的文本、页面、图片、视频等。GET请求参数的位置一般是写在URL当中,URL规定只能支持ASCII,所以GET请求的参数只允许ASCII字符,而且浏览器会对URL的长度有限制(HTTP协议本上对URL长度没有做规定)。

  • POST

    根据RFC规范,POST请求的语义是根据请求负荷(报文body)对指定资源做出处理,处理的具体方式视资源类型而不同、POST请求携带数据的位置一般是在报文body中,body中的数据可以是任意格式的数据,只要客户端与服务器协商好即可,并且浏览器不会对body大小做限制。

    比如,在我文章底部的评论区留言后,点击提交,浏览器就会执行一次POST请求,把你们的留言文字放进报文body里,然后拼接好POST请求头,通过TCP协议发送到服务器。

GET和POST方法是否都安全和幂等

首先说明一下安全和幂等的概念:

  • 在HTTP协议中,所谓的安全试制请求方法会不会破坏服务器上的资源。
  • 所谓的幂等,是指多次执行相同的操作,结果是否都是相同的。

如果从RFC规范定义的语义来说:

  • GET方法是安全且幂等的,因为他是只读操作,无论操作多少次,服务器上的数据都是安全的,并且每次的结果也是相同的。所以,可以对GET方法请求的数据做缓存,这个缓存可以放到浏览器上,也可以放到代理上(如Nginx)。
  • POST方法因为是新增或修改数据操作,会修改服务器上的资源,所以是不安全的,而且多次提交数据就会创建多个资源所以不是幂等的。

需要注意的,上面说的都是基于RFC规范定义的语义来分析的,实际开发中,开发者不一定会按照规范来实现GET和POST方法,比如:

  • 可以使用GET方法来实现新增或删除数据的请求,这样GET方法就是不安全、不幂等的。
  • 可以使用POST方法来实现数据查询的请求,这样POST方法就是安全和幂等的。

有一个笑话,有人写了个博客,删除博客用的是GET请求,他觉得没人访问就连鉴权都没做。

然后Google服务器爬虫爬了一遍,他所有博文就没了。

HTTP缓存技术

HTTP缓存的实现方式

对于一些重复性的HTTP请求,比如每次请求得到的数据都一样,我们可以把这对「请求-响应」的数据缓存到本地,那么下一次请求就可以直接读取本地的数据了,不需要通过网络获取服务器的响应,这样的话HTTP/1.1的性能会有肉眼可见的提升。

所以避免发送同样HTTP请求的方法就是通过缓存技术,HTTP设计者早在之前就考虑到了这点,所以HTTP协议的头部有不少字段都是针对缓存设计的。

HTTP缓存的实现方式总体上可以分为两种,分别是强制缓存和协商缓存。

强制缓存

前置缓存指的是只要浏览器判断缓存没过期,则直接使用浏览器本地的缓存,决定是否使用缓存的主动性在浏览器。

如下图,返回的状态码是200,但是括号中的标识是赖在内存缓存,也就是使用了强制缓存。

HTTP常见面试问题_第5张图片

强制缓存是利用下面这两个HTTP响应头部(Response Header)字段来实现的,他们都用来表示资源在客户端缓存的有效期:

  • Cache-Control,是一个相对时间;
  • Expires,是一个绝对时间;

如果HTTP响应头同时有这两个字段的话,Cache-Controle的优先级高于Expire

Cache-Control的选项更多一些,设置更加精细,所以建议使用Cache-Control来实现强缓存。具体实现流程如下:

  • 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在Response头中加上Cache-Control这个字段,该字段中设置了资源过期时间的长度。
  • 当浏览器再次请求该资源时,会先通过请求该资源的时间与Cache-Control中设置过期的时间大小来计算出该资源是否过期,如果没有,则使用改缓存,否则重新请求服务器。
  • 当资源过期后,服务器再次收到请求,会重复上述步骤。

协商缓存

当我们在浏览器使用开发者工具的时候,可能看到过某些请求的响应码是304,这个是告诉浏览器可以使用本地缓存的资源,通常这种服务端告知客户端是否可用使用缓存的方式被称为协商缓存。

协商缓存可以基于两种头部字段来实现。

  1. 基于请求头中的If-Modified-Since字段与响应头部中的Last-Modified字段实现
    • 响应头中的Last-Modified:表示这个响应资源最后修改的时间,服务器给客户端返回资源的时候会带上。
    • 请求头中的If-Modified-Since:当需要再次请求服务器该资源的时候,客户端会将该资源的修改时间作为If-Midified-Since的值放到请求头,一起发送给服务器,服务器收到后返现有If-Modified-Since,则将该资源的最后修改时间与之对比,若最后修改时间较新,则说明资源又被修改过,则返回新资源,HTTP 200 OK;如果最后修改时间较旧,则返回HTTP 304,浏览器继续使用本地缓存。
  2. 请求头部中的 If-None-Match 字段与响应头部中的 ETag 字段
    • 响应头中的Etag:唯一标识响应资源。
    • 请求头中的If-None-Match:当资源过期时,浏览器发现该资源的响应头中有Etag,则再次向服务器发起请求时,会将请求头中的If-None-Match的值设为Etag的值。服务器收到请求后就行对比,如果资源没有变化则返回HTTP 304,如果变化了则返回新的资源,HTTP 200 OK。

下图就是一个Etag协商的过程。
HTTP常见面试问题_第6张图片

第一种方式是基于时间来实现的,而第二种方式是基于一个位移标识来实现的,相对来说后者可以更加准确地判断出文件内容是否被修改该,避免时间被篡改而导致的不可靠问题。

如果HTTP响应头同时有Etag和Last-Modified字段的时候,Etag的优先级更高,就是先会通过判断Etag是否变化了,如果未发生变化,再看Last-Modified。

注意:协商缓存这两种方法都需要配合强制缓存中的Cache-Control字段来使用,只有在未命中强制缓存的时候,才可以发起带有协商缓存字段的请求。

下图是浏览器判断缓存是否过期的完整流程。

HTTP常见面试问题_第7张图片

HTTP特性

HTTP/1.1的优点

HTTP最突出的优点是「简单、灵活和易于扩展、应用广泛和快平台」。

  1. 简单

    HTTP报文基本格式就是header + body,头部信息也是key-value的简单文本形式,易于理解,降低了学习和使用的门槛。

  2. 灵活和易于扩展

    HTTP协议里的各类请求方法、URI/URL、状态码、头部字段等每个组成要求都没有被固定死,都允许开发人员自定义和扩充。

    同时HTTP由于是工作在应用层(OSI第七层),则他下层可以随意变化。

    HTTPS也就是在HTTP与TCP层之间增加了SSL/TLS安全创术层,HTTP/3甚至吧TCP层换成基于UDP的QUIC。

  3. 应用广泛和跨平台

    互联网发展至今,HTTP的应用范围非常的广阔,从台式机的浏览器到手机上的各种APP,HTTP的应用遍地开花,同时具有跨平台的优越性。

HTTP/1.1的缺点

HTTP协议里有优缺点一题的双刃剑,分别是「无状态、明文传输」,同时还有一大缺点「不安全」。

  1. 无状态双刃剑

    无状态的好处,因为服务器不需要去记忆HTTP的状态,所以不需要额外的资源来记录状态信息,这可以减轻服务器的负担,能够把更多的CPU和内存来对外提供服务。

    无状态的坏处,没有记忆的服务器,在完成一些关联性的操作时会非常麻烦,例如:登录->添加购物车->下单->结算->支付,这一系列操作都要知道用户的身份才行。单服务器不知道这些请求是有关联的,每次都要问一遍身份信息,这就显得非常的“不聪明”。

    对于无状态的问题,解决方案也有多种,比较简单的方式是使用Cookie技术,通过在请求和响应报文中写入Cookie信息来控制客户端的状态。

    Cookie就相当于一个“小贴纸”, 在客户端第一次请求后,服务器会下发一个装有客户信息的“小贴纸”,后续客户端请求服务器的时候,带上“小贴纸”,服务器就认识这是谁了。

HTTP常见面试问题_第8张图片

  1. 明文双刃剑

    明文意味着在传输的过程中不需要对信息进行加密和解密,可以在一定程度上减少客户端和服务器的性能消耗。

    但也正是这样,HTTP所有的信息都暴露在光天化日之下,相当于信息裸奔了,在明文传输的漫长过程中,很容易就会被别人窃取,如果里面有你的账号密码信息,那就相当于号没了。

  2. 不安全

    HTTP比较严重的缺点就是不安全:

    • 明文通信,内容可能被窃听。比如上面说的号没了
    • 不验证通信方的身份,可能会遭遇伪装。比如访问假的淘宝、京东,那钱没了
    • 无法验证报文的完整性,有可能内容会被篡改。比如在网页上植入垃圾广告,视觉污染,眼没了

    HTTP的安全问题可以用HTTPS的方式来解决,也就是通过引入SSL/TLS层,使得安全性可靠。

HTTP/1.1性能

HTTP是基于TCP/IP,并且使用了「请求 - 应答」的通信模式,所以性能关键就在这两点。

  1. 长连接

    早起的HTTP/1.0性能上有一个比较大的问题,那就是每次发起一个请求,都要新建一次TCP连接(三次握手),而且是串行请求,做了很多无谓的TCP连接建立和断开,增加了通信开销。

    为了解决上述问题,HTTP/1.1提出了长连接的通信方式,也叫持久连接,这种方式的好处在于减少了TCP连接的重复建立和断开所带来的的额外开销,减轻了服务器端的负载。

    持久连接的特点是,只要任意一端没有明确要断开连接,就保持TCP连接的状态。

    HTTP常见面试问题_第9张图片

    当然如果HTTP长连接超过一定时间没有数据交互,服务器就会主动断开这个连接。

  2. 管道网络传输

    HTTP/1.1采用了长连接的方式,这使得管道(pipeline)网络传输称为可能。

    也就是在同一个TCP连接中,客户端可以发起多个请求,主要第一个请求发出去了,不需要邓起返回,就可以发出第二个请求,可以减少真题的响应时间。

    煮个栗子,客户端需要请求两个资源,之前的做法是,在同一个TCP连接里面先发送A请求,然后等服务器做出回应,收到后在发出B请求。那么,管道机制是允许浏览器同时发出A请求和B请求。

    但是服务器必须按照接收请求的顺序发送这些请求的响应。

    这就会出现一种情况,如果服务器在处理A请求时耗时比较长,那么后续的请求处理都会被阻塞,这被称为「队头阻塞」。所以HTTP/1.1解决了请求的队头阻塞,但是没有解决响应的队头阻塞。

    注意:实际上HTTP/1.1管道化技术不是默认开启的,而且浏览器基本都没有支持,所以后面讨论HTTP/1.1都是建立在没有使用管道化的前提。

  3. 对头阻塞

    「请求 - 应答」的模式加剧了HTTP的性能问题。

    因为当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也同样被阻塞了,会导致客户端一直请求不到数据,这就是队头阻塞。

    HTTP常见面试问题_第10张图片

总之,HTTP/1.1的性能比较一般,后续的HTTP/2和HTTP/3就是在优化HTTP的性能。

HTTP与HTTPS

HTTP与HTTPS的区别

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

HTTPS解决了HTTP的哪些问题

众所周知,HTTP是明文传输,所以安全上存在一下三点风险:

  • 窃听风险,在通信连路上可以获取通信的内容。
  • 篡改风险,在通信链路上可以被强行植入垃圾广告。
  • 冒充风险,冒充淘宝等购物网站。

HTTP常见面试问题_第11张图片

而HTTPS在HTTP与TCP层之间加入了SSL/TLS协议,可以很好的解决上述的风险:

  • 信息加密:通过混合加密算法对交互的信息进行加密,中间人无法窃取通信内容,保证通信内容的机密性,解决了窃听风险。
  • 校验机制:通过摘要算法生成通信内容的数字签名,通过该签名可以判断通信的内容是否被篡改,保证通信内容的完整性,解决了篡改风险。
  • 身份证书:通过数字证书来保证我们使用的公钥不是冒充的,解决了冒充风险。

下面详细介绍这三项解决措施:

  1. 混合加密

    HTTP常见面试问题_第12张图片

    HTTPS采用的是对称加密和非对称加密结合的混合加密方式:

    • 在通信建立之前采用非对称加密的方式来交换会话秘钥,后续就不再使用非对称加密。
    • 在通信过程中全部使用会话秘钥来进行对称加密通信,减轻系统的性能消耗。

    采用混合加密的原因:

    • 对称加密只使用一个秘钥,运算速度快,但是秘钥必须保密,无法做到安全的秘钥交换。
    • 非对称加密使用两个秘钥,一个公钥一个私钥,公钥可以任意分发而私钥必须保密,解决了秘钥交换问题但速度较慢。
  2. 摘要算法+数字签名

    为了保证传输的内容不被篡改,我们需要对内容计算出一个「指纹」,然后同内容一起传输给对方,对方收到数据后,也对内容计算出一个「指纹」,然后更发送方的「指纹」做一个比较,如果「指纹」相同,说明内容没有被篡改,否则就可以判断内容被篡改过。

    HTTP常见面试问题_第13张图片

    在计算机中,会使用摘要算法(哈希函数)来计算内容的哈希值,也就是内容的「指纹」,这个哈希值是唯一的,且无法通过哈希值推导出内容,也就是哈希的过程是不可逆的。

    通过摘要算法虽然可以保证内容不会被篡改,但是并不能保证内容和哈希值不会被一起修改掉,因为这里缺少对客户端收到的消息是否来源于服务器的证明。

    为了避免这种情况的发生,这里通常会使用非对称加密算法来解决,非对称加密的两个秘钥可以双向加密和解密,比如用公钥加密,私钥解密,也可以用私钥加密,公钥解密,这两种不同的做法,目的也完全不同:

    • 公钥加密,私钥解密:这个目的是为了保证传输内容的安全,因为公钥加密的内容其他人是无法解密的,只有持有私钥的人才可以解密出实际内容。
    • 私钥加密,公钥解密:这是为了确保消息没有被冒充,因为私钥是保密的,如果公钥可以正常解密出私钥加密的内容,说明这个消息是来自于持有私钥身份的人发送的。

    一般我们不会使用非对称加密来解密实际的传输内容,因为非对称加密比较耗费性能。非对称加密一般是通过「私钥加密,公钥解密」的方式,来确认消息的身份,数字签名算法,就是采用这种方式,不过私钥加密的内容不是内容本身,而是对内容的哈希值加密。

    到这里,完整的流程如下图:

    HTTP常见面试问题_第14张图片

    私钥是有服务端保管,然后服务端会向客户端分发对应的公钥,如果客户端收到的信息能被公钥解密,就说明该消息是由服务器发送的。

  3. 数字证书

    通过前面我们知道:

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

    但还是存在存在着一个漏洞,缺少了对公钥的验证,万一公钥是被伪造的,那前面的这些加密都白搭。

    所以还需要一个权威机构来证明公钥的身份,这个全为机构就是CA(数字证书认证机构),将服务器公钥放在数字证书(数字证书认证机构颁发)中,只要证明证书可信的,那公钥就是可信的。

    数字证书的工作流程如下图:
    HTTP常见面试问题_第15张图片

    通过数字证书的方式可以保证服务器公钥的身份,解决冒充的风险。

参考资料

小林coding HTTP常见面试问题

你可能感兴趣的:(http,面试,网络)