Http发展历史

1. 什么是http

Hypertext Transfer protocol
超文本传输协议
是一个基于 响应(响应状态码)和请求(Get/Post区别)
无状态(Session和Cookies)的,
应用层的协议。
常基于TCP/IP协议传输数据,所有的www文件都必须遵守这个标准
设计Http的初衷是为了提供一种发布和接受Html脚本的方法

2.发展历史

版本 产生时间 内容 发展现状
HTTP/0.9 1991
HTTP/1.0 1996 增加了一些方法
HTTP/1.1 1997 长连接,分块传输 目前为止最广泛
HTTP/2 2015 多路复用,头信息压缩

Https Http http1.0->http1.1 - 图1
HTTP2
多个请求共享一个TCP连接
image.png

HTTPS


HTTPS加密机制

  1. 场景1:客户端服务端明文传输

攻击者可以抓取明文获取信息
wireshark

  1. 场景2:客户端服务端之间用对称加密

Https Http http1.0->http1.1 - 图3
问题:
服务端:客户端 是 一对多的关系
所以服务端 给所有客户端的 密钥 A 是一样的

攻击者可以先充当正常客户端,获得密钥A,那么就能够解密了

  1. 场景3:非对称加密传输

Https Http http1.0->http1.1 - 图4
客户端只能获取公钥

服务端有公钥和私钥

step1:
客户端请求公钥
step2:
服务端返回公钥
step3:
客户端用公钥加密数据 传输给服务端
step4:
服务端用私钥解密,获取报文

但是服务端要怎么向客户端发送数据呢?
第一种:用公钥加密
====》》》客户端无法解密
第二种:用私钥加密
====》》》攻击者也可以很容易地获取公钥进行解密

所以非对称加密只能保证客户端向 服务器端的可靠传输

  1. 场景4:用两对公私钥进行非对称加密

Https Http http1.0->http1.1 - 图5
看起来可行

中间人攻击?

但是问题是,非对称加密计算时间会长

HTTPS的加密却没使用这种方案,为什么?最主要的原因是非对称加密算法非常耗时,特别是加密解密一些较大数据的时候有些力不从心。而对称加密快很多。那我们能不能运用非对称加密的特性解决前面提到的对称加密的问题?

  1. https实现思路

对称加密,如果每个客户端都有一个key的话,那确实是安全传输
非对称加密,服务器端向客户端发的是不安全的

那就通过组合
每个客户端都获得一个key
而且是安全的

因为客户端向服务端发送数据时可靠的

那么,就按照非对称加密

获取到公钥
随机定义一个字符串(或者数字?真随机伪随机?)
这样就可以获得一个攻击者无法获取的 Y

作为 对称加密的密钥
Https Http http1.0->http1.1 - 图6

  1. 场景6:中间人攻击

黑客假装自己是服务器端

中间人用假公钥+假私钥
就可以获得客户端随机生成的字符串
Https Http http1.0->http1.1 - 图7

中间人攻击不安全:
根本原因是浏览器无法确认自己收到的公钥是不是网站自己的。那么下一步就是解决这个问题:如何证明浏览器收到的公钥一定是该网站的公钥?

  1. 场景:引入CA

只有经过权威机构认证的公钥才认为是好公钥

用户向服务端索要 Pk,现在不直接给了
对Pk进行加密
使用 CaSk对Pk进行加密
f(CaSk,Pk) = license

私钥加密是用作签名

客户端请求license

客户端要得到pk
那么就要有 CaPk(Ca的公钥)

那么拿CaPk的过程仍然有可能被中间人截获

所以干脆在客户端,写死在操作系统中(还是浏览器?)


HTTPS过程

  • C-> S 发送支持的SSL版本,非对称算法,随机数1 ——1
  • S->C 用相应版本的SSL,对称算法,随机数2,证书 ——-2
  • C证书认证 —-ok ——-3
  • C->S 随机数3 用数字证书的公钥签名随机数3===》》》 ———4
  • S:用数字证书的私钥,获取随机数3
  • C,S都根据约定的加密算法,使用前面3个随机数,生成 “会话密钥”

现在一般不会选择RSA算法
会用DH算法

  1. 其他

image.png
image.png
windows查看根证书信任机构

image.png

image.png

  1. 证书的申请

证书的申请主要包括:
(1)向证书公司提交生成的证书请求文件(CSR)
(2)证书公司对CSR进行签名生成签名证书
(3)证书公司向客户反馈生成的证书链(客户证书、中间证书、根证书)

  1. SSL和TLS

SSL是安全套接字层
TLS是传输层安全
TLS是SSL的继承协议

HTTP1.0->HTTP1.1

host头

HTTP1.1规定必须加Host头

keep alive

缓存

image.png
这是服务器响应的HTTP报文


HTTP缓存控制小结

1.通用首部字段

字段名称 说明
Cache-Control 控制缓存的行为
Pragma HTTP1.0的历史遗留,值为”no-cache”时禁用缓存

chrome浏览器 F12之后,network中点 Disable Cache就禁用cache了
image.png
另外,在Http1.1协议下,Pragma优先级要比cache-control优先级高
因为Http1.1要向下兼容HTTP1.0,而HTTP1.0根本不识别cache-control,所以Pragma优先级更高。

2. 请求首部字段

字段名称 说明
IF-Match 比较Etag是否一致
If-None-Match 比较Etag是否不一致
IF-Modified-Since 比较资源最后更新的时间是否一致
IF-UnModified-Since 比较资源最后更新的实践是否不一致

使用cache后:

请求:
image.png

3. 响应首部字段

响应:

字段名称 说明
Etag 资源的匹配信息

image.png
image.png

4. 实体首部字段

字段名称 说明
Expires HTTP1.0的遗留产物,实体主体过期的时间
Last-Modified 资源最后一次修改的时间

想要做出有Last-Modified的响应,还得自己开个服务器啊

请求的时候
If-Match之类的带上Last-Modified字段,是最后一次的修改时间
响应的时候的,Etag字段就是服务器最后一次的修改时间
如果二者不匹配
重新加载,然后返回服务器的Last-Modified字段
如果二者一致,也就是匹配
那就返回304,Not Modified

image.png

问题:
队头阻塞
不能先返回请求2,再返回图片1

HTTP2.0

头部压缩
二进制分帧层(binary framing layer)

1.0、1.1、2测评

https://www.bilibili.com/video/BV1p541147LD/

image.png
总结下来:
http2 TCp连接只有一个
Http1 TCP连接因为可以keep alive 所以也不需要那么多,但是浏览器有限制,
chorme是限制6个

节省流量的同时,也可以加载更多的数据

问题

1. Get/Post区别

Get 和 Post 是 HTTP 中最常用的两个方法,基本上使用 HTTP 方法中有 99% 都是在使用 Get 方法和 Post 方法,所以有必要我们对这两个方法有更加深刻的认识。
Get和Post没有本质区别,只是报文格式不同(也就是语义化的约定不同)

Https Http http1.0->http1.1 - 图19Mark:

  • 关于数据包

firefox 浏览器Post请求时只发送一次数据包

  • Get会被网络上各种奇怪的中间节点缓存(如CDN)缓存,POST不会
  • 关于URL长度,其实Get后边加很多参数也没关系,因为URL没有长度限制,只是浏览器会限制URL长度!!
  • 关于安全,,,,GET放URL,能直接看见参数,POST放HTML的body里,点Network一样能看到啊,只有用HTTPS才是安全.(如果不被看到算安全的话也算吧)
  • 关于缓存的理解:

按照规范
Get是获取数据的,所以可以做缓存,这个缓存可以

  • 浏览器缓存,再次请求时就可以直接查浏览器缓存
  • 代理缓存,那代理就可以不用查服务器了
  • 服务器缓存(用Etag)

Post一般用来提交form
如果Post下单,然后服务器根据Post修改了
浏览器响应修改成功
如果有缓存,下一次相同的Post请求,浏览器就可以直接把自己的响应成功页面拿过来
但是,实际上这一次的Post请求没有到达服务器

Get是向服务器发 索取数据的一种请求 Post是向服务器发 提交数据的一种请求


2. Http1.1相对Http1.0有哪些不同

  1. 长连接 : 在HTTP/1.0中,默认使用的是短连接,也就是说每次请求都要重新建立一次连接。HTTP 是基于TCP/IP协议的,每一次建立或者断开连接都需要三次握手四次挥手的开销,如果每次请求都要这样的话,开销会比较大。因此最好能维持一个长连接,可以用个长连接来发多个请求。HTTP 1.1起,默认使用长连接 ,默认开启Connection:keep-alive。 HTTP/1.1的持续连接有非流水线方式和流水线方式 。流水线方式是客户在收到HTTP的响应报文之前就能接着发送新的请求报文。与之相对应的非流水线方式是客户在收到前一个响应后才能发送下一个请求。
  2. 错误状态响应码 :在HTTP1.1中新增了24个错误状态响应码
  3. 缓存处理 :在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
  4. 带宽优化及网络连接的使用 :HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。

3. Sha1,Sha256,MD5

这个会问才有鬼

4. “在keep-alive模式下,客户端如何判断服务器已经发送完了数据(即客户端如何知道自己已经接收完数据了)?”(一个十年前的问题)

1)使用消息首部字段Conent-Length
Conent-Length表示实体内容长度,当客户端向服务器请求一个静态页面或者一张图片时,服务器可以很清楚的知道内容大小,然后通过Content-length消息首部字段告诉客户端 需要接收多少数据。

是服务器端知道静态页面或者图片大小,客户端知道 Content_length之后就知道接受完了。

2)使用消息首部字段Transfer-Encoding
如果是动态页面等时,服务器是不可能预先知道内容大小。因为对于动态生成的内容来说,在内容创建完之前,长度是不可知的。这时候要想准确获取长度,只能开一个足够大的 buffer,等内容全部生成好再计算。但这样做一方面需要更大的内存开销,另一方面也会让客户端等更久。所以不可能这么做。Conent-Length就失效了。

另外:
Keep-Alive timeout:
Httpd守护进程,一般都提供了keep-alive timeout时间设置参数。比如nginx的keepalive_timeout,和Apache的KeepAliveTimeout。这个keepalive_timout时间值意味着:一个http产生的tcp连接在传送完最后一个响应后,还需要hold住keepalive_timeout秒后,才开始关闭这个连接。
当httpd守护进程发送完一个响应后,理应马上主动关闭相应的tcp连接,设置 keepalive_timeout后,httpd守护进程会想说:”再等等吧,看看浏览器还有没有请求过来”,这一等,便是keepalive_timeout时间。如果守护进程在这个等待的时间里,一直没有收到浏览器发过来http请求,则关闭这个http连接。

Tcp的Keepalive:
连接建立之后,如果客户端一直不发送数据,或者隔很长时间才发送一次数据,当连接很久没有数据报文传输时如何去确定对方还在线,到底是掉线了还是确实没有数据传输,连接还需不需要保持,这种情况在TCP协议设计中是需要考虑到的。
TCP协议通过一种巧妙的方式去解决这个问题,当超过一段时间之后,TCP自动发送一个数据为空的报文(侦测包)给对方,如果对方回应了这个报文,说明对方还在线,连接可以继续保持,如果对方没有报文返回,并且重试了多次之后则认为链接丢失,没有必要保持连接。
tcp keep-alive是TCP的一种检测TCP连接状况的保鲜机制。tcp keep-alive保鲜定时器,支持三个系统内核配置参数:
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_time = 1800
keepalive是TCP保鲜定时器,当网络两端建立了TCP连接之后,闲置(双方没有任何数据流发送往来)了tcp_keepalive_time后,服务器就会尝试向客户端发送侦测包,来判断TCP连接状况(有可能客户端崩溃、强制关闭了应用、主机不可达等等)。如果没有收到对方的回答(ack包),则会在 tcp_keepalive_intvl后再次尝试发送侦测包,直到收到对方的ack,如果一直没有收到对方的ack,一共会尝试 tcp_keepalive_probes次,每次的间隔时间在这里分别是15s, 30s, 45s, 60s, 75s。如果尝试tcp_keepalive_probes,依然没有收到对方的ack包,则会丢弃该TCP连接。TCP连接默认闲置时间是2小时,一般设置为30分钟足够了。