http协议知识点整理

 

http文档:https://tools.ietf.org/html/rfc2616

1.前言

这篇文章主要是我平时在学习HTTP过程中看到的一些知识点,现在把他们总结成一篇文章,建立一个自己的知识体系

1.1基础知识铺垫

OSIOpen System Interconnection的缩写,意为开放式系统互联

OSI7层框架 如图:

1)应用层(dns,http)DNS解析域名为IP并发送http地址

2)传输层(tcp,udp)建立tcp连接(三次握手)

3)网络层(IP,ARP)IP寻址

4)数据链路层(PPP)封装成帧

今天的主角是http:http是基于TCP/IP协议的应用层协议,用于客户端和服务器之间的通信HTTP是一个无状态的协议。

1.2在TCP/IP协议栈中的位置

HTTP协议通常承载于TCP协议之上,有时也承载于TLSSSL协议层之上,这个时候,就成了我们常说的HTTPS。如下图所示:
    

默认HTTP的端口号为80HTTPS的端口号为443

2. HTTP发展历程

  1. HTTP/0.9版本,这个时候的HTTP只支持GET请求,且不支持请求头,
  2. HTTP/1.0版本,这是第一个在通讯中指定版本号的HTTP协议版本,至今仍被广泛采用,特别是在代理服务器中。
  3. HTTP/1.1版本,持久连接被默认建立,并能很好地配合代理服务器工作。还支持以管道方式在同时发送多个请求,以便降低线路负载,提高传输速度。现在使用最广泛的。
  4. HTTP/2.0版本,当前版本,于2015年5月作为互联网标准正式发布。

3.HTTP请求

HTTP请求第一步,应该是由客户端发起一个HTTP请求,当然这个客户端可以是例如我们的浏览器,F12调试,发起我们的第一个请求头信息。

http报文一般包括:通用头部、请求/响应头部、请求/响应体

假设我们现在开始请求CSDN主页

通用头部:

请求头部

响应头部

说一点:Content-Length当浏览器使用持久http连接才需要。

如果存在Transfer-Encoding(重点是chunked),则在header中不能有Content-Length,有也会被忽视

这里插一句,HTTP/1.1沿用的是文本类型的请求头,HTTP/2则会使用二进制数据。

 

4.HTTP是如何建立连接的

说道如何连接的,我们必须要回顾一个东西,那就是大学学到过的计算机网络基础,几乎所有的大学生都应该了解过计算机的网络模型,也就是我们熟知的七层网络模型,如下图

但是计算机网络中的七层模型毕竟是理想中的情况,现实是很少有应用实现了七层模型,一般都是整合其中两个或多个,实现一个四层或者五层的模型。

TCP/IP模型

在这里我们研究的是HTTP,自然要知道它所处在哪个模型中,答案是应用层。这里要引入一个TCP/IP的概念,大家应该知道,TCP处于传输层,IP属于网络层,而我们这里所探究的HTTP,实际上就是基于TCP/IP协议开发的,至于TCP/IP的网络模型,它没有照搬计算机网络的七层模型,而是整合了表示层,会话层应用层,统一为应用层,比较有争议的是,关于TCP/IP究竟是几层协议,目前为止没有定论,一般我比较习惯统称为四层协议,至于别人说的五层协议,其实就是数据链路层,物理层是不是一层有所争议吧。如图:

因为HTTP是基于TCP/IP开发的协议,看过HTTP协议的同学肯定都知道,有句话概述HTTP协议为无差错的协议按序传输未分段的数据流,这其实说的就是TCP协议。

 

5 发送一条HTTP请求会发生什么?

当你在浏览器输入一个URL的时候,有没有想过这其中发生了什么?

  1. 获取主机名,例如:http://www.nowamagic.net/academy/

  2. 通过DNS获取服务器IP

  3. 获取端口,默认是80端口
  4. 连接到 121.199.24.143:80服务器

  5. 通过TCP信道发送一个HTTP请求

  6. 服务器读取一个HTTP请求

  7. 服务器查找所需资源并通过TCP信道返回资源

  8. 关闭TCP连接

6 .字段解释

通用头部

这也是开发人员见过的最多的信息,包括如下:

Request Url: 请求的web服务器地址

Request Method: 请求方式(Get、POST、OPTIONS、PUT、HEAD、DELETE、CONNECT、TRACE)

Status Code: 请求的返回状态码,如200代表成功

Remote Address: 请求的远程服务器地址(会转为IP)

这里面最常用到的就是状态码,很多时候都是通过状态码来判断,如(列举几个最常见的):

200——表明该请求被成功地完成,所请求的资源发送回客户端
304——自从上次请求后,请求的网页未修改过,请客户端使用本地缓存
400——客户端请求有错(譬如可以是安全模块拦截)
401——请求未经授权
403——禁止访问(譬如可以是未登录时禁止)
404——资源未找到
500——服务器内部错误
503——服务不可用

再列举下大致不同范围状态的意义

1xx——指示信息,表示请求已接收,继续处理
2xx——成功,表示请求已被成功接收、理解、接受
3xx——重定向,要完成请求必须进行更进一步的操作
4xx——客户端错误,请求有语法错误或请求无法实现
5xx——服务器端错误,服务器未能实现合法的请求

请求/响应头部

请求和响应头部也是分析时常用到的

常用的请求头部(部分):

Accept:接收类型,表示浏览器支持的MIME类型(对标服务端返回的Content-Type)
Accept-Encoding:浏览器支持的压缩类型,如gzip等,超出类型不能接收
Content-Type:客户端发送出去实体内容的类型
Cache-Control:指定请求和响应遵循的缓存机制,如no-cache
If-Modified-Since:对应服务端的Last-Modified,用来匹配看文件是否变动,只能精确到1s之内,http1.0中
Expires:缓存控制,在这个时间内不会请求,直接使用缓存,http1.0,而且是服务端时间
Max-age:代表资源在本地缓存多少秒,有效时间内不会请求,而是使用缓存,http1.1中
If-None-Match:对应服务端的ETag,用来匹配文件内容是否改变(非常精确),http1.1中
Cookie:有cookie并且同域访问时会自动带上
Connection:当浏览器与服务器通信时对于长连接如何进行处理,如keep-alive
Host:请求的服务器URL
Origin:最初的请求是从哪里发起的(只会精确到端口),Origin比Referer更尊重隐私
Referer:该页面的来源URL(适用于所有类型的请求,会精确到详细页面地址,csrf拦截常用到这个字段)
User-Agent:用户客户端的一些必要信息,如UA头部等

常用的响应头部(部分):

Access-Control-Allow-Headers: 服务器端允许的请求Headers
Access-Control-Allow-Methods:服务器端允许的请求方法
Access-Control-Allow-Origin:服务器端允许的请求Origin头部(譬如为*)
Content-Type:服务端返回的实体内容的类型
Date:数据从服务器发送的时间
Cache-Control:告诉浏览器或其他客户,什么环境可以安全的缓存文档
Last-Modified:请求资源的最后修改时间
Expires:应该在什么时候认为文档已经过期,从而不再缓存它
Max-age:客户端的本地资源应该缓存多少秒,开启了Cache-Control后有效
ETag:请求变量的实体标签的当前值
Set-Cookie:设置和页面关联的cookie,服务器通过这个头部把cookie传给客户端
Keep-Alive:如果客户端有keep-alive,服务端也会有响应(如timeout=38)
Server:服务器的一些相关信息

一般来说,请求头部和响应头部是匹配分析的。

譬如,请求头部的Accept要和响应头部的Content-Type匹配,否则会报错

譬如,跨域请求时,请求头部的Origin要匹配响应头部的Access-Control-Allow-Origin,否则会报跨域错误

譬如,在使用缓存时,请求头部的If-Modified-SinceIf-None-Match分别和响应头部的Last-ModifiedETag对应

7.HTTPS

HTTPS = HTTP+加密+认证+完整性保护

它的加密过程是:

1.浏览器请求建立SSL链接并向服务端发送一个随机数Client random和客户端支持的加密方法比如RSA加密此时是明文传输
2.服务端从中选出一组加密算法与Hash算法回复一个随机数Server random并将自己的身份信息以证书的形式发回给浏览器证书里包含了网站地址非对称加密的公钥以及证书颁发机构等信息
3.浏览器收到服务端的证书后:

       -验证证书的合法性颁发机构是否合法证书中包含的网址是否和正在访问的一样),如果证书信任则浏览器会显示一个小锁头否则会有提示

      -用户接收证书后不管信不信任),浏览会生产新的随机数Premaster secret然后证书中的公钥以及指定的加密方法加密`Premaster secret`发送给服务器

      -利用Client randomServer random和Premaster  secret通过一定的算法生成HTTP链接数据传输的对称加密key-`session key`

      -使用约定好的HASH算法计算握手消息并使用生成的`session key`对消息进行加密最后将之前生成的所有信息发送给服务端.


       

4. 服务端收到浏览器的回复

    -利用已知的加解密方式与自己的私钥进行解密获取`Premaster secret`

    -和浏览器相同规则生成`session key`

    -使用`session key`解密浏览器发来的握手消息并验证Hash是否与浏览器发来的一致

    -使用`session key`加密一段握手消息发送给浏览器

5. 浏览器解密并计算握手消息的HASH如果与服务端发来的HASH一致此时握手过程结束.

8. http2.0

http2.0不是https,它相当于是http的下一代规范(譬如https的请求可以是http2.0规范的)

然后简述下http2.0与http1.1的显著不同点:

http1.1中,每请求一个资源,都是需要开启一个tcp/ip连接的,所以对应的结果是,每一个资源对应一个tcp/ip请求,由于tcp/ip本身有并发数限制,所以当资源一多,速度就显著慢下来

http2.0中,一个tcp/ip请求可以请求多个资源,也就是说,只要一次tcp/ip请求,就可以请求若干个资源,分割成更小的帧请求,速度明显提升。

所以,如果http2.0全面应用,很多http1.1中的优化方案就无需用到了(譬如打包成精灵图,静态资源多域名拆分等)

然后简述下http2.0的一些特性:

  • 多路复用(即一个tcp/ip连接可以请求多个资源)
  • 首部压缩(http头部压缩,减少体积)
  • 二进制分帧(在应用层跟传送层之间增加了一个二进制分帧层,改进传输性能,实现低延迟和高吞吐量)
  • 服务器端推送(服务端可以对客户端的一个请求发出多个响应,可以主动通知客户端)
  • 请求优先级(如果流被赋予了优先级,它就会基于这个优先级来处理,由服务器决定需要多少资源来处理该请求。)
 

9. 跨域

跨域产生的原因,是因为受到同源策略的限制。同源策略指的是协议、域名、端口不相同。这里我将介绍三种跨域的方式:JSONP、CORS(跨域资源共享)、document.domain + iframe。

9.1 JSONP

1. 原理

动态插入script标签(因为script标签不受同源策略的限制),通过插入script标签引入一个js文件,这个js文件加载成功之后会执行我们在url中指定的回调函数,并且会把我们需要的json数据作为参数传入。

2. 实现

(1)原生实现:

var script = document.createElement('script');
script.type = 'text/javascript';
// 传参并指定回调执行函数为onBack
script.src = 'http://www.domain2.com:8080/login?user=admin&callback=onBack';
document.head.appendChild(script);
// 回调函数
function onBack(res) 
{
   alert(JSON.stringify(res));
}
//服务端返回如下(返回时即执行全局函数):
onBack({"status": true, "user": "admin"})

(2)jquery ajax:

$.ajax({url:'http://www.domain2.com:8080/login',    
type: 'get',
dataType: 'jsonp',  // 请求方式为jsonp
jsonpCallback: "onBack", // 自定义回调函数名
data: {}
});

9.2 CORS

1. 原理

服务器在响应头中设置相应的选项,浏览器如果支持这种方法的话就会将这种跨站资源请求视为合法,进而获取资源。

2. 实现

CORS分为简单请求和复杂请求,简单请求指的是:

(1)请求方法是以下三种方法之一:HEAD、GET、POST;

(2)HTTP的头信息不超出以下几种字段:Accept、Accept-Language、Content-Language、Last-Event-ID、
         Content-Type(只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)。

其他情况就是非简单请求了。

  • 简单请求

(1)请求头

Origin: http://www.domain.com

(2)响应头

Access-Control-Allow-Origin: http://www.domain.com
Access-Control-Allow-Credentials: true //`是否允许传送cookie`
Access-Control-Expose-Headers: FooBar //`CORS请求时,只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须指定。`

(3)另外,ajax请求中,如果要发送Cookie,Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名,还要设置以下内容:

var xhr = new XMLHttpRequest();

xhr.withCredentials = true;
 
  • 非简单请求

(1)预检请求:

OPTIONS /cors HTTP/1.1  `OPTIONS请求是用来询问的`
Origin: http://www.domian.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header

(2)响应头

Access-Control-Allow-Origin: http://www.domain.com
Access-Control-Allow-Methods: GET, POST, PUT  `服务器支持的所有跨域请求的方法`
Access-Control-Allow-Headers: X-Custom-Header  `服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。`
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000  `指定本次预检请求的有效期,单位为秒`

(3)之后的步骤就同简单请求了

这是CORS的整个流程图:

 

与JSOP的比较

JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

猜你喜欢

转载自blog.csdn.net/ycq521131/article/details/81712995