HTTP/HTTPS协议无疑是面试中最常问的几个计网协议之一。然而网上很多博客都写得偏简略,不够全面。于是我便打算做一个整合。内容较多,大致会分为三篇博客,一篇介绍HTTP协议,一篇介绍SSL/TLS协议,一篇介绍HTTPS协议。
HTTP协议也叫超文本传输协议,它定义了客户端和服务器的通信格式。是一种基于请求和响应、无状态的应用层协议。传输层采用TCP协议,具备可靠的数据传输。接下来我们便从HTTP请求、HTTP响应、版本更替三个方面来看一下HTTP。
一、HTTP请求
(一)、定义
HTTP请求是客户端往服务端发送请求动作,告知服务器自己的要求。
(二)、数据报格式
HTTP请求数据格式由请求行、请求头部和请求主体三部分组成:
1、状态行:包括请求方式Method、资源路径URL、协议版本Version;
2、请求头:包括一些访问的域名、用户代理、Cookie等信息;
3、请求正文:就是HTTP请求的数据。
(三)、补充知识点
1、请求方法的种类
GET --- 访问服务器的资源
POST --- 向服务器发送要修改的数据
HEAD --- 获取服务器文档的首部
PUT --- 向服务器上传资源
DELETE --- 删除服务器的资源
2、GET和POST的区别
#get一般用于从服务器上获取数据,post一般用于向服务器传送数据
#请求的时候参数的位置有区别,get的参数是拼接在url后面,用户在浏览器地址栏可以看到。post是放在http包的包体中。
#能提交的数据有区别,get方式能提交的数据只能是文本,且大小不超过1024个字节,而post不仅可以提交文本还有二进制文件。
二、HTTP响应
(一)、定义
服务器收到了客户端发来的HTTP请求后,根据HTTP请求中的动作要求,服务端做出具体的动作,并将结果回应给客户端,称为HTTP响应。
(二)、数据报格式
HTTP响应由三部分组成:响应行、响应头部和响应主体;
1、状态行:包括协议版本Version、状态码Status Code、回应短语;
2、响应头:包括搭建服务器的软件,发送响应的时间,回应数据的格式等信息;
3、响应正文:就是响应的具体数据。
(三)、补充知识点
1、五种响应状态码
1开头的表示HTTP请求已经接受,继续处理请求
2开头的表示HTTP请求已经处理完成
3开头的表示把请求访问的URL重定向到其他目录
4开头的表示客户端出现错误
5开头的表示服务端出现错误
常见的几种状态码含义如下
200---/请求已经正常处理完毕
301---/请求永久重定向
302---/请求临时重定向
304---/请求被重定向到客户端本地缓存
400---/客户端请求存在语法错误
401---/客户端请求没有经过授权
403---/客户端的请求被服务器拒绝,一般为客户端没有访问权限
404---/客户端请求的URL在服务端不存在
500---/服务端永久错误
503---/服务端发生临时错误
三、HTTP的版本更替
(一)、HTTP0.9
HTTP协议的最初版本,功能简陋,仅支持请求方式GET,并且仅能请求访问HTML格式的资源。
(二)、HTTP1.0
在0.9版本上做了改进,一是增加了请求方式POST和HEAD;二是资源不再局限于HTML格式(content-type首部行);三是开始支持cache,当客户端在规定时间内访问同一网站,直接访问cache即可。
但是1.0版本的工作方式是每次TCP连接只能发送一个请求,当服务器响应后就会关闭这次连接,下一个请求需要再次建立TCP连接。即采用非持续性连接,不支持keepalive。非持续性连接存在两个缺点,一是必须对所有的对象都维护一条全新的连接,在客户端和服务器都要分配TCP的缓存区和TCP变量,给服务器带来严重的负担。二是所有的请求对象都要经受两倍RTT的时延。
(三)、HTTP1.1
在1.0的版本上做了改进,一是解决了1.0版本非持续性连接的问题,1.1版本加入了持续性连接(connection首部行,keep-alive),一个TCP连接可以允许多个发送HTTP请求;二是加入了管道机制,一个TCP连接允许多个请求同时发送,增加了并发性;(举例来说,客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送A请求,然后等待服务器做出回应,收到后再发出B请求。管道机制则是允许浏览器同时发出A请求和B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求。)三是新增了请求方式PUT、PATCH(更新资源)、DELETE等。四是支持断点续传。HTTP
但是它也仍然存在着一些问题,一个是服务端是按队列顺序处理请求的,假如一个请求处理时间很长,则会导致后边的请求无法处理,这样就造成了队头阻塞的问题;同时HTTP是无状态的连接,因此每次请求都需要添加重复的字段,降低了带宽的利用率。
(四)、HTTP2.0
为了解决1.1版本利用率不高的问题,提出了HTTP/2.0版本。所做的改进主要有三个。
一是增加双工模式,即不仅客户端能够同时发送多个请求,服务端也能同时处理多个请求,解决了HTTP request级别的队头堵塞问题;
二是对字段头部进行压缩。HTTP请求和响应中,状态行和请求/响应头都是些信息字段,并没有真正的数据,因此在2.0版本中将所有的信息字段建立一张表,为表中的每个字段建立索引,客户端和服务端共同使用这个表,他们之间就以索引号来表示信息字段,这样就避免了1.1旧版本重复繁琐的字段,并以压缩的方式传输,提高利用率。
三是另外也增加服务器推送的功能,即不经请求服务端主动向客户端发送数据。
至于HTTP3.0,我们放到最后再来介绍,相较于前几个版本,它已经发生了巨大的变化了。
四、其他常见的问题
(一)、HTTP协议如何处理粘包问题
HTTP采用TCP进行通信,而TCP是面向数据流传输的,容易出现粘包问题。HTTP采用的解决方案主要有两个:
1、content-length字段
content-length字段声明了本次回应的数据长度。TCP协议保证了数据能够按序交付,结合content-length字段即可划分数据包所属的回应。但是使用content-length字段的前提条件是,服务器在发送回应前必须知道回应数据的长度。对于一些很耗时的操作来说,这意味着服务器要等到所有操作完成,才能发送数据,显然这样的效率不高。
2、Transfer-Encoding字段
Transfer-Encoding,即分块传输编码,采用“流模式”,产生一块数据就发送一块,效率更高。只要请求或回应的头信息有Transfer-Encoding字段,就表明回应将由数量未定的数据块组成。每个非空的数据块之前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为0的块,就表示本次回应的数据发送完了。
(二)、HTTP协议无状态的解决方案——身份认证机制
1、BASIC认证
#基本认证步骤:
A、客户端访问一个受http基本认证保护的资源。
B、服务器返回401状态,要求客户端提供用户名和密码进行认证。(验证失败的时候,响应头会加上WWW-Authenticate: Basic realm="请求域"。)
401 Unauthorized
WWW-Authenticate: Basic realm="WallyWorld"
C、客户端将输入的用户名密码用Base64进行编码后,采用非加密的明文方式传送给服务器。
Authorization: Basic xxxxxxxxxx.
D、服务器将Authorization头中的用户名密码解码并取出,进行验证,如果认证成功,则返回相应的资源。如果认证失败,则仍返回401状态,要求重新进行认证。
#特点
A、Http是无状态的,同一个客户端对同一个realm内资源的每一个访问会被要求进行认证。
B、客户端通常会缓存用户名和密码,并和authentication realm一起保存,所以,一般不需要你重新输入用户名和密码。
C、以非加密的明文方式传输,虽然转换成了不易被人直接识别的字符串,但是无法防止用户名密码被恶意盗用。虽然用肉眼看不出来,但用程序很容易解密。
2、摘要认证digest authentication
#这个认证可以看做是基本认证的增强版本,不包含密码的明文传递。即客户端通过某种哈希算法计算出自身用户名和密码的哈希值(即又叫response值),然后将其发送给服务器进行身份验证。因为服务器拥有与客户端同样的信息,因此服务器可以进行同样的计算,以验证客户端提交的 response 值的正确性。并且由于哈希计算是不可逆的,即理论上通过response值来逆推出用户名和密码是不可能的,因此提高了通信的安全性。
#response值的计算
主要分为三步。其中当多个数值合并的时候,使用冒号作为分割符:
A、对用户名、认证域(realm)以及密码的合并值计算 MD5 哈希值,结果称为 HA1。
B、对HTTP方法以及URI的摘要的合并值计算 MD5 哈希值,例如,"GET" 和 "/dir/index.html",结果称为 HA2。
C、对HA1、服务器密码随机数(nonce)、请求计数(nc)、客户端密码随机数(cnonce)、保护质量(qop)以及 HA2 的合并值计算 MD5 哈希值。结果即为客户端提供的response 值。
3、cookie/session 认证
用户输入用户名和密码发起请求,服务器认证通过后分配一个唯一的SESSIONID发送给客户端。当客户端发起新的请求的时候,将携带上这个SESSIONID来表明自己的身份。这样服务器便能够找到这个客户端对应的Session。默认的,当我们关闭浏览器的时候,客户端cookie会被删除,可以通过修改cookie 的expire time使cookie在一定时间内有效。但是服务器端的session不会被销毁,除非通过invalidate或超时。
补充:cookie和session的区别:两者都是用于记录客户端状态的机制。cookie将客户端状态(比如用户账号和密码)保存在本地的一个txt文件中,session则是把用户账号和密码信息保存在服务器上,客户端保存的只是sessionID。从安全性上来看,session的用户账号和密码存储在服务器上,会比cookie更安全,但是两者都无法避免会话被劫持的问题。从性能上来看,session由于把客户状态信息保存在了服务器上,从而占用了一定了内存,性能不如cookie好。
4、Token 认证
#Token认证可以看做是cookie/session认证的增强,它新增了签名字段防止信息被篡改,并将获取到的客户端信息用非对称加密算法进行加密后,得到一个token,再把Token存储在数据库中。
#认证过程
token认证和cookie认证差不多,
A、首次登陆,用户名和密码验证过之后,将sessionId保存在token中,或者将一个key保存在token中,key的值可以设置为用户唯一性的信息(账号/密码/身份认证机制(电话号/身份证号/支付宝账号/银行卡信息)...);设置token的有效期,并保存在服务器数据库中;
B、服务器将这个token值返回给客户端,客户端拿到 token 值之后,将 token 保存在 cookie 中,以后客户端再次发送网络请求(一般不是登录请求)的时候,就会将这个 token 值附带到参数中发送给服务器。服务器接收到客户端的请求之后,会取出token值与保存在本地(数据库)中的token值做对比!
C、如果两个 token 值相同 :说明用户登录成功过!当前用户处于登录状态!如果没有这个token或者过期,则设置token为无效,并让用户重新登录。
#优点
A、减轻服务器压力:通过token可以将用户的基本信息(非隐私的,比如UserId,过期时间,生成的随机key等)全部加密签名后放入token中,从而服务器端不需要保存用户登录信息,大大减轻服务器压力。
B、用户认证完全靠token识别,通过签名来保证token没有被修改过(只有服务器才知道秘钥,比如常见的非对称加密算法),是服务器下发的token。
C、支持跨域访问:因为服务器并没有保存登录状态,完全靠签名的token识别,那么另一个网站只要有对应的私钥,就可以对token验证,前提是传输的用户认证信息通过HTTP头传输;
D、更适用CDN: 可以通过内容分发网络请求你服务端的所有资料(如:javascript,HTML,图片等),因为不需要同步服务器上的登录状态信息;(CDN是未来一个很重要的发展方向)
E、性能更好: 因为从token中可以获得userId,不用查询登录状态表;
(三)、Web缓存与条件GET
Web缓存服务器位于客户和Web服务器之间。它有自己的磁盘存储空间,能够在存储空间中保存最近请求过对象的副本。当客户下次再请求相同副本时,便可以直接从Web缓存器中获得。并且Web缓存器通过条件GET机制来保证客户能够取到最新的对象。举例来说,假设当前浏览器正在请求一个对象,将会发生如下情况:
A、浏览器创建一个到Web缓存器的TCP连接,并向Web缓存器发送一个关于该对象的HTTP请求;
B、Web缓存器接收到HTTP请求后,查看本地是否有被请求对象的副本。假设该对象是一个新对象,Web缓存器没有该对象的副本。那么Web缓存器将会打开一个到该对象初始服务器的TCP连接,并向其发送一个关于该对象的HTTP请求。
C、Web服务器接收到该请求后,发送一个具有该对象及最后修改时间(即Last-modified字段)的HTTP响应
D、Web缓存器接收到响应后,在本地存储空间存储一份该对象的副本及其Last-modified的值,并向客户的浏览器发送该副本。
之后如果有其他浏览器再次向该Web缓存服务器请求该对象时,由于Web缓存器在本地查找到了该对象的副本,它会先给Web服务器发送一个条件GET执行最新检查。该请求报文包含请求对象和对象最后被修改的时间(If-modified-since字段)。该条件GET告诉服务器仅当在指定日期后该对象被修改过才发送该对象。Web服务器会进行相应判断,如果该对象在指定日期之后没有再被修改,则发送一个带有Not Modified短语的响应报文,不包含该对象。否则则发送一个带有新的对象及新的Last-modified值的响应报文。