文章目录
- 一、HTTP概述
- 二、HTTP协议的过程
- 三、HTTP请求与响应
- 四、HTTP报文
- [五、HTTP cookie 与 session](#五、HTTP cookie 与 session)
HTTP ( HyperText Transfer Protocol )是 超文本传输协议 ,是无状态协议。即服务器不会保存客户端的状态信息。
HTTP 是一个用在计算机世界里的协议 。它使用计算机能够理解的语言确立了一种计算机之间交流通信的规范(两个以上的参与者 ),以及相关的各种控制和错误处理方式(行为约定和规范)。
一、HTTP概述
1、HTTP的理解
HTTP协议是目前应用最广泛的应用层网络协议。应用层协议HTTP协议是Web的核心。HTTP协议在Web客户端(浏览器)和服务器程序中得以实现。运行在不同系统上的客户程序和服务器程序,通过交换HTTP消息彼此交流。HTTP定义了请求和响应的消息格式,使得客户端和服务器能够进行有效的通信。
Web页面(web page,也称为文档)是通过HTTP协议在客户端和服务器之间传输的基本内容,它通常由一个HTML文件和多个引用的对象组成。注:对象可以是HTML文件、图像(如JPG、PNG)、音频、视频、JavaScript、CSS等。
也就是说浏览器是Web的用户代理,它显示所请求的Web页面,并提供大量的导航与配置特性。Web浏览器还实现了HTTP的客户端,因此在web上下文中,可以从进程意义上互换使用"浏览器"和"客户"。
Web页面大多数由一个基本HTML文件和很多HTML文件中所引用的对象构成。例如,如果某个 Web页面包含1个HTML文本文件和5个PNG图像,这个 Web页面就由6个对象构成,即基本 HTML文件加5个图像。这个基本的HTML 文件使用文件中的内置URL来引用本页面中所使用的其他对象,例如上述的5个PNG图像需要在基本HTML文件中进行 URL 的引用定义。
2、HTTP是无状态的协议
HTTP是无状态的协议。HTTP协议自身不对请求和响应之间的通信状态进行保存。也就是说在HTTP这个级别,协议对于发送过的请求或响应都不做持久化处理。
使用 HTTP 协议,每当有新的请求发送时,就会有对应的新响应产生。协议本身并不保留之前一切的请求或响应报文的信息。这是为了更快地处理大量事务,确保协议的可伸缩性,而特意把 HTTP 协议设计成如此简单的。
可是,随着 Web 的不断发展,因无状态而导致业务处理变得棘手的情况增多了。比如,用户登录到一家购物网站,即使他跳转到该站的其他页面后,也需要能继续保持登录状态。针对这个实例,网站为了能够掌握是谁送出的请求,需要保存用户的状态。
HTTP/1.1 虽然是无状态协议,但为了实现期望的保持状态功能,于是引入了 Cookie 技术。有了 Cookie 再用 HTTP 协议通信,就可以管理状态了。有关 Cookie 的详细内容稍后讲解。
HTTP也被描述为无连接协议,因为在HTTP/1.0中,每个请求/响应对使用一个单独的TCP连接。客户端发送请求后,服务器发送响应,随后关闭连接。这种无连接的方式使得资源的释放更为高效,但也带来了较高的连接开销。但是每次请求都需要新建和关闭TCP连接,这增加了连接建立和拆除的开销(如三次握手和四次挥手)。
在HTTP/1.0中,每个请求/响应对之后会关闭TCP连接,涉及到TCP的四次挥手过程。HTTP/1.1引入了持久连接(keep-alive),允许多个请求/响应对复用同一个TCP连接,从而减少连接开销。
持久连接 (HTTP Persistent Connections),也称为HTTP keep-alive,或长连接,是为了解决HTTP协议中的TCP连接频繁建立和断开的问题。
在HTTP协议的早期版本中,每进行一次HTTP通信(例如请求一个网页或其资源),都会建立一个新的TCP连接,并在通信结束后断开。这种方式在当时的文本传输中影响不大,但随着网页包含的资源(如图片、脚本等)增多,这种方式会导致频繁的TCP连接建立和断开,从而增加了通信的开销和延迟。
HTTP/1.1引入了持久连接的概念,默认情况下,所有连接都是持久的。持久连接的好处在于减少了TCP连接的重复建立和断开,从而减轻了服务器的负载并降低了通信延迟。只要任意一端没有明确提出断开连接,TCP连接将保持开放状态,允许进行多个HTTP请求和响应。持久连接减少了TCP连接建立和断开的开销,使得HTTP请求和响应能够更快地完成,从而提高了网页加载速度和整体用户体验。
Connection: keep-alive
是HTTP首部字段,用于指示客户端和服务器之间的连接应保持开放,以便进行多个请求和响应。这一机制是持久连接的实现方式之一。
二、HTTP协议的过程
HTTP协议是基于客户端/服务器之间的请求响应进行交互的。
上图为一个客户端和服务器之间HTTP协议访问基本过程。
一个客户端与服务器建立连接后,发送一个请求给服务器,请求方式的格式为:统一资源标识符,协议版本号,后边是MIME信息包括请求修饰符、客户端信息和可能的内容。
服务器接到客户端请求后,向客户端发送相应的响应信息,其格式为:一个状态行包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。
互联网上,HTTP(超文本传输协议)的通信通常是建立在TCP/IP协议之上的。一般来说,HTTP通信使用的默认端口是TCP协议的80端口,尽管也可以使用其他端口。然而,这并不意味着HTTP协议可以在互联网或其他网络中的其他协议之上进行传输,HTTP的数据传输是依赖于TCP协议的。
在万维网(WWW)中,"客户"和"服务器"的概念是相对的,它们只在特定的连接中具有意义。在某个连接中扮演客户角色的实体,在另一个不同的场景下可能充当服务器的角色。当万维网服务器运行时,它会持续在TCP的80端口(即万维网的默认端口)上进行监听,以便随时响应和处理出现的连接请求。
互联网是物理网络的基础设施,而万维网(一个基于超文本方式的信息查询方式)是这个基础设施上的一种服务或应用,它允许用户通过网页浏览和访问互联网上的信息。没有互联网,万维网就无法存在;而互联网除了万维网之外,还有许多其他用途和服务。
具体来说,基于HTTP协议的客户/服务器模式的信息交换过程分为4个过程:建立链接,发送请求信息、发送响应信息、关闭连接。
1、URL(统一资源定位符)
URL(Uniform Resource Locator,统一资源定位符)用于标识互联网上的资源,包括网页、图片、视频等。一个URL由2部分构成:存放该对象的服务器主机名和该对象的路径名。
- 域名或IP :这部分标识了存放资源的网络服务器的位置。主机名可以是IP地址,也可以是域名。例如,在URL
http://www.example.com/index.html
中,www.example.com
是域名,或称服务器主机名,此处也可以是IP地址。 - 对象路径名 :这部分标识了服务器上资源的路径。例如,在URL
http://www.example.com/index.html
中,/index.html
是对象路径名,它指明了服务器上的资源文件。 - 协议名 :协议名指明了如何访问资源,最常见的是
http
和https
。http
是超文本传输协议,https
是其安全版本,提供加密连接。比如,URLhttp://www.example.com/index.html
使用的是http
协议,而https://www.example.com/index.html
使用的是https
协议。
完整的URL包括协议(如 http:
或 https:
)、域名和对象路径名。例如,上述URL表示的是通过HTTP协议访问位于 www.example.com
服务器上的 /index.html
文件。
最后可能还跟着提供服务的服务器端口。(可以省略,因为每个协议都有自己的标准端口)若一个服务器没有使用标准的端口提供服务,我们才需要指定端口。
urlencode
和urldecode
是处理URL中特殊字符编码的标准方法。对于URL中的特殊字符(如/
、?
、:
等),这些字符具有特定的意义,因此必须对其进行转义,以确保数据的正确传输和解析。URL编码(
urlencode
)是将特殊字符转换为%
后跟随两位十六进制数字的格式。将需要转义的字符转换为其ASCII码,再把ASCII码转换为两位十六进制数,最后将十六进制数前加上%
符号,形成%XY
格式。上图中,我们搜索C++,
+
在URL是特殊字符,因此被转化为%2B
。URL 解码(
urldecode
)是将%XY
格式的编码转换回原始字符的过程。我们可以使用https://tool.oschina.net/进行解码:
一般来说,一个浏览器被使用者选中了一个超文本链接后,浏览器通常会执行以下几个步骤来处理请求并显示相应的内容:
-
解析URL:
- 提取协议、主机名和路径 :浏览器解析超文本链接中的URL,提取协议(如
http
或https
)、主机名(如www.example.com
)和路径(如/index.html
)。 - DNS解析:如果URL中使用的是域名,浏览器会使用DNS(域名系统)将域名解析为IP地址。
- 提取协议、主机名和路径 :浏览器解析超文本链接中的URL,提取协议(如
-
建立网络连接
- 建立TCP连接 :浏览器通过解析得到的IP地址与服务器建立TCP连接。对于
https
链接,这一步还会包括建立TLS/SSL加密连接。
- 建立TCP连接 :浏览器通过解析得到的IP地址与服务器建立TCP连接。对于
-
发送HTTP请求
-
生成请求 :浏览器生成一个HTTP请求,包括请求行(如
GET /index.html HTTP/1.1
)、请求首部(如Host
和User-Agent
)和(如果需要)请求体。 -
发送请求:将生成的HTTP请求通过TCP连接发送到目标服务器。
-
-
处理HTTP响应
-
接收响应 :服务器收到HTTP请求后,生成HTTP响应。响应包括状态行(如
HTTP/1.1 200 OK
)、响应首部(如Content-Type
和Content-Length
)以及响应体(即请求的资源内容)。 -
解析响应:浏览器接收HTTP响应并解析响应首部和响应体。
-
-
渲染内容
-
解析HTML:如果响应体是HTML文档,浏览器将解析HTML,构建DOM(文档对象模型)树。
-
解析CSS:浏览器解析HTML中引用的CSS样式,并将其应用于DOM树中的元素。
-
解析JavaScript:浏览器解析和执行HTML中包含的JavaScript脚本,可能会修改DOM或触发其他操作。
-
渲染页面:浏览器根据DOM和CSS构建页面的渲染树,并将其绘制到屏幕上。
-
-
处理资源
-
加载资源:如果HTML文档中包含其他资源(如图片、视频、外部CSS文件和JavaScript文件),浏览器会发送额外的HTTP请求来获取这些资源。
-
更新页面:在获取到所有必要资源后,浏览器会更新页面的显示内容。
-
-
关闭连接
-
保持连接:根据HTTP协议和服务器的配置,浏览器可能会保持连接以处理后续请求(如使用HTTP长连接)。
-
关闭连接:如果不再需要连接,浏览器会关闭与服务器的TCP连接。
-
DNS(Domain Name System ,域名系统)解析是将域名转换为IP地址的过程。它允许用户使用易于记忆的域名(如
www.example.com
)访问互联网资源,而不是直接使用难以记忆的IP地址(如192.0.2.1
)。
ping
命令会先调用系统的 DNS 解析功能,将域名解析为 IP 地址。这通常涉及到查询本地 DNS 缓存、操作系统缓存、以及可能的外部 DNS 服务器。域名和 IP 地址在技术上是等价的。域名和 IP 地址可以互换使用。浏览器和其他应用程序会通过 DNS 解析将域名转换为 IP 地址,进行实际的网络通信。
2、客户端
从使用者的角度来看,万维网(Web)是一个包含丰富图像、文字和多媒体信息的网络资源集合,这些资源通常被我们称为"网页"或简称"页面"。每个网页都不仅仅是孤立的内容,它们还包含了指向其他网页的"链接"(或称为"连接")。
这些链接是万维网的核心特征之一,它们允许用户通过简单的点击操作,从一个页面跳转到另一个页面。这种通过连接在不同页面间进行跳转的特性,定义了"超文本"(hypertext)的概念。
"超文本"是一个描述文档中包含指向其他文档链接的概念。这些链接不仅限于文本,也可以是图像、按钮或其他任何可点击的元素。超文本的这种特性使得万维网成为一个互联的信息网络,用户可以在其中自由探索和发现内容。
为了访问和浏览这些页面,用户需要使用一种专门的软件程序,即"浏览器"(Browser)。
当用户通过浏览器发出请求以获取某个页面时,浏览器会发送一个请求到服务器,服务器再将页面内容返回给浏览器。浏览器随后会解释页面中的HTML(超文本标记语言)和其他控制命令,并将页面内容以视觉友好的方式展示给用户。
Web 页面当然不能凭空显示出来。根据 Web 浏览器地址栏中指定的URL,Web 浏览器从 Web 服务器端获取文件资源(resource)等信息,从而显示出 Web 页面。这种通过发送请求获取服务器资源的 Web 浏览器等,都可称为客户端(client)。
具体来说:客户端是指浏览器向网络服务器发送网页和图像请求。服务器处理完请求后,将响应发送回客户端,一旦响应完成,TCP连接将被关闭(在HTTP/1.0中),或者保持连接以便进行后续请求(在HTTP/1.1中)。
3、服务器端
每一个Web服务器上面都运行着一个侦听TCP的80端口的进程来等待来自客户端的HTTP请求(一般来说,都是Web Browser发送这个请求)。也就是说Web服务器在80端口上等待客户端的连接请求。客户端(如Web浏览器)通过向该端口发起TCP连接来请求访问Web内容。当一个连接发生时,客户端发送一个请求,服务器收到请求后,服务器会将客户端所请求的数据返回给客户端。
简单来说:请求访问文本或图像等资源的一端称为客户端,而提供资源响应的一端称为服务器端。
在两台计算机之间使用 HTTP 协议通信时,在一条通信线路上必定有一端是客户端,另一端则是服务器端。
三、HTTP请求与响应
Web 请求是指客户端(如Web浏览器)向服务器发送的请求,以获取或发送信息。用户通过点击有超文本链接的文字或图像,浏览器会显示点击链接对应的网页或资源。Web 使用 HTTP的协议作为规范,完成从客户端到服务器端等一系列运作流程。而协议是指规则的约定。可以说,Web 是建立在 HTTP 协议上通信的。
HTTP 协议规定,请求从客户端发出,最后服务器端响应该请求并返回。换句话说,肯定是先从客户端开始建立通信的,服务器端在没有接收到请求之前不会发送响应。
1、HTTP请求和响应
HTTP 请求是指客户端(如浏览器)向服务器发送的请求,用于获取资源或与服务器进行交互。HTTP 请求使用 HTTP(超文本传输协议)进行通信,协议规定了请求的格式和响应的处理方式。下图是从客户端发送给服务器端的请求报文中的内容:
在HTTP请求中,起始行的第一个词表示HTTP请求方法 。HTTP请求方法定义了客户端想要对服务器上的资源执行的操作类型。随后的字符串 /2.html
指明了请求访问的资源对象,也叫做请求URL。最后的HTTP/1.1
是指 HTTP 的版本号,这个版本号用来告诉服务器客户端支持HTTP/1.1协议规范,包括该版本特有的功能和行为。
综合这些信息,我们可以理解这个HTTP请求是在请求位于服务器 8.130.182.84
上端口 8888
的 2.html
页面,并且客户端期望服务器以HTTP/1.1协议规范来处理这个请求。
因此我们可以发现:请求报头是由请求方法、请求URL、协议版本、可选的请求首部字段和内容实体构成的。
请求报文的完整构成如下:
请求首部字段及内容实体稍后会作详细说明。接下来,我们继续讲解。接收到请求的服务器,会将请求内容的处理结果以响应的形式返回。
在起始行开头的 HTTP/1.0 表示服务器对应的 HTTP 版本。紧接着的200 OK 表示请求处理结果的状态码和原因短语。后面还有创建响应的日期时间,是首部字段内的属性。还有一个空行,空行后面的内容称为资源实体的主体。
因此我们可以发现:响应报文由协议版本、状态码(表示请求成功或失败的数字代码)、用以解释状态码的原因短语、可选的响应首部字段以及实体主体构成。
稍后我们会对这些内容进行详细说明。响应报文的完整构成如下:
为什么请求和响应的状态行需要有HTTP版本?
HTTP 版本确保了客户端和服务器能够正确地理解和处理消息。
-
确定协议版本:HTTP 协议有多个版本(如 HTTP/1.0、HTTP/1.1等),每个版本都有不同的功能和特性。指定 HTTP 版本能够帮助客户端和服务器知道使用哪个版本的协议进行通信。
-
保持向后兼容:HTTP 版本允许客户端和服务器保持向后兼容。即使客户端使用较新的 HTTP 版本,服务器仍可以使用较旧的版本,并且相互之间仍能进行通信。
-
功能支持和差异:不同版本的 HTTP 协议支持不同的功能和特性。例如:
-
HTTP/1.0:每次请求都需要建立一个新的连接。
-
HTTP/1.1:引入了持久连接和请求流水线,提高了性能。
-
HTTP/2:引入了多路复用、首部压缩等特性,进一步提升了性能。
-
HTTP/3:基于 QUIC 协议,进一步减少延迟并提高了连接的可靠性。
-
通过在请求和响应中指定 HTTP 版本,客户端和服务器可以协商使用的特性和功能。
-
正确解析和处理消息:不同版本的 HTTP 协议在解析和处理消息时可能有不同的要求。例如,HTTP/1.1 要求所有的请求和响应头必须以 CRLF(回车换行)结尾,而 HTTP/2 则使用二进制格式进行传输。指定 HTTP 版本有助于确保客户端和服务器能够正确解析和处理消息。
-
错误处理:HTTP 版本也可以用于错误处理。如果服务器不支持客户端请求的 HTTP 版本,它可以返回一个错误响应,告知客户端不支持的版本信息。
HTTP版本信息在请求和响应中起到了确保协议一致性、提供功能特性、处理错误和支持协议扩展等重要作用。
2、HTTP请求方法
在HTTP请求中,起始行的第一个词表示HTTP请求方法。HTTP请求方法定义了客户端想要对服务器上的资源执行的操作类型。
请求方法 | 描述 | 支持的 HTTP协议版本 |
---|---|---|
GET | 获取资源 | 1.0、1.1 |
POST | 传输实体主体 | 1.0、1.1 |
PUT | 传输文件 | 1.0、1.1 |
HEAD | 获得报文首部 | 1.0、1.1 |
DELETE | 删除文件 | 1.0、1.1 |
OPTIONS | 询问支持的方法 | 1.1 |
TRACE | 追踪路径 | 1.1 |
CONNECT | 要求用隧道协议连接代理 | 1.1 |
LINK | 建立和资源之间的联系 | 1.0 |
UNLINE | 断开连接关系 | 1.0 |
这些方法允许客户端与服务器进行各种交互,包括获取信息、提交数据、更新资源等
其中我们最常用的就是GET和POST方法。
GET方法具体来说,就是用来请求访问已被URL识别的资源。指定的资源经服务器端解析后返回响应的内容。即,从服务器获取指定的资源。 这个资源可以是静态的文本、页面、图片视频等。GET 请求的参数位置一般是写在 URL 中,URL 规定只能支持 ASCII,所以 GET 请求的参数只允许 ASCII 字符 ,例如http://example.com/page?id=123
。而且浏览器会对 URL 的长度有限制(HTTP协议本身对 URL长度并没有做任何规定)。
POST方法是用来传输实体主体,即发送数据到服务器。通常用于提交表单数据。POST请求的参数包含在请求体的正文中,不会显示在URL中,因此相对安全。由于URL长度有限,POST方法能通过正文传递更多数据。
虽然用GET也可以传输实体的主体,但一般不用GET方法进行传输,而是用POST方法。虽然POST的功能与GET很类似,但POST的主要目的并不是获取相应的主题内容。
那么GET和POST方法都是安全的吗?
如果我们从路由是否可以看到GET/POST的数据来说:使用POST方法传参更加私密,因为POST方法不会将你的参数回显到URL当中,此时也就不会被别人轻易看到。但不能说POST方法比GET方法更安全,因为POST方法和GET方法实际都不安全。所以,要注意安全性的话,就要使用 HTTPS 协议,这样所有 HTTP 的数据都会被加密传输。
如果从RFC规范的定义来说:GET是安全且幂等。POST是不安全且不幂等的。
这里的所谓安全就是指请求方法不会破坏服务器上的资源。而幂等是指执行多次相同的操作,结果都是相同的。
GET是进行只读 操作,无论操作什么操作多少次服务器上的资源都是安全的,而且结果相同。POST是进行新增或提交数据操作,会修改服务器上的资源,且多次提交数据就会创建多个资源。
3、状态码
状态码告知从服务器端返回的请求结果。状态码的职责是当客户端向服务器发送请求时,描述返回的请求结果。借助状态码,用户可以知道服务器端是正常处理了请求,还是出现了错误。
状态码如 200 OK,以 3 位数字和原因短语组成。数字中的第一位指定了响应类别,后两位无分类。响应类别有以下 5种:
状态码类型 | 范围 | 描述 |
---|---|---|
信息性状态码 | 1XX |
这些状态码表示服务器收到请求,需要客户端继续执行操作。 |
成功响应状态码 | 2XX |
这些状态码表示服务器成功处理了请求。 |
重定向状态码 | 3XX |
这些状态码表示请求需要进一步的操作才能完成。 |
客户端错误状态码 | 4XX |
这些状态码表示客户端的请求有语法错误,不能被服务器理解。 |
服务器错误状态码 | 5XX |
这些状态码表示服务器在处理请求时发生了错误。 |
下面我们介绍几种常用的状态码:
- 200 OK:请求成功,服务器返回请求的资源。这是最常见的状态码,表示服务器成功处理了客户端发送的请求。
- 204 No Content:与200 OK基本相同,请求成功,但服务器没有返回任何内容。
- 301 Moved Permanently:永久性重定向。请求的资源已被永久移动到新位置。当服务器上的资源移动到新的URL时,返回此状态码,并包含新的URL。
- 302 Found:临时性重定向。请求的资源已被临时移动到新位置。当服务器上的资源临时移动到新的URL时,返回此状态码,并包含新的URL。
- 403 Forbidden:表明对请求资源的访问被服务器拒绝了。未获得文件系统的访问授权,访问权限出现某些问题(从未授权的发送源 IP 地址试图访问)等列举的情况都可能是发生 403 的原因。
- 404 Not Found:请求的资源不存在。当客户端请求的资源在服务器上不存在时,返回此状态码。
- 500 Internal Server Error:服务器遇到内部错误。当服务器无法处理请求时,返回此状态码。
四、HTTP报文
HTTP 协议的请求和响应报文中必定包含 HTTP 首部,只是我们平时在使用 Web 的过程中感受不到它。
报文首部在客户端和服务器处理时最需要的信息大部分都在这里面。报文主体是HTTP报文的实际数据部分,包含了所请求或响应的内容。报文主体的内容取决于请求或响应的具体操作。
HTTP报文分为两个主要部分:报文首部和报文主体。
报文首部:
- 作用:报文首部包含了一系列键值对,这些键值对提供了关于请求或响应的元数据,如请求的方法、URL、状态码、内容类型、服务器信息等。
- 格式 :每个键值对由一个名字和一个冒号(:)分隔,然后是值,例如
Content-Type: text/html
。 - 分隔 :报文首部由两个字节的序列(CR+LF)分隔,即回车符(
\r
)和换行符(\n
)。
报文主体:
- 作用:报文主体包含了请求或响应的实际数据,如HTML页面内容、JSON数据、文件内容等。
- 格式 :报文主体可以是任意数据,其长度由报文首部中的
Content-Length
字段指定。 - 分隔:报文主体在HTTP/1.1中位于最后一个空行之后,但在HTTP/1.0中,如果存在报文主体,它会在最后一个空行之后。
请求报文和响应报文的首部内容由一系列的键值对组成,这些键值对被称为首部字段。请求报文和响应报文的首部内容由以下数据组成:请求行,状态行,各种首部字段。
1、请求报文首部
请求报文由方法,URL、HTTP版本、HTTP首部字段构成。如下(GET请求):
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
User-Agent: Mozilla/5.0
2、响应报文首部
响应报文由 HTTP 版本、状态码(数字和原因短语)、HTTP 首部字段 3 部分构成。如下(200 OK响应):
HTTP/1.1 200 OK
Date: Tue, 03 Aug 2024 14:30:00 GMT
Content-Type: text/html
Content-Length: 1234
3、首部字段
HTTP首部字段是HTTP报文的重要组成部分,无论是在请求还是响应中,都要包含这些字段。它们用于传递额外的控制信息和元数据,帮助客户端和服务器进行有效的通信。一般有 4 种首部,分别是:通用首部、请求首部、响应首部和实体首部。
通用首部字段 (General Header Fields):请求报文和响应报文两方都会使用的首部。
首部字段名 | 说明 |
---|---|
Cache-Control |
控制缓存的行为 |
Connection |
连接的管理 |
Date |
创建报文的日期时间 |
Pragma |
报文指令 |
Trailer |
报文末端的首部一览 |
Transfer-Encoding |
指定报文主体的传输编码方式 |
Upgrade |
升级为其他协议 |
Via |
代理服务器的相关信息 |
Warning |
错误通知 |
Connection :字段最常用于客户端要求服务器使用「HTTP 长连接」机制,以便其他请求复用。HTTP/1.1 版本的默认连接都是长连接,但为了兼容老版本的 HTTP,需要指定
Connection
首部字段的值为Keep-Alive
。
textConnection: Keep-Alive
注意:HTTP Keep-Alive 和 TCP Keepalive 不是同一个东西。
请求首部字段 (Request Header Fields):从客户端向服务器端发送请求报文时使用的首部。补充了请求的附加内容、客户端信息、响应内容相关优先级等信息。
首部字段名 | 说明 |
---|---|
Accept |
用户代理可处理的媒体类型 |
Accept-Charset |
优先的字符集 |
Accept-Encoding |
优先的内容编码 |
Accept-Language |
优先的语言(自然语言) |
Authorization |
Web认证信息 |
Expect |
期待服务器的特定行为 |
From |
用户的电子邮箱地址 |
Host |
请求资源所在服务器 |
If-Match |
比较实体标记(ETag) |
If-Modified-Since |
比较资源的更新时间 |
If-None-Match |
比较实体标记(与 If-Match 相反) |
If-Range |
资源未更新时发送实体 Byte 的范围请求 |
If-Unmodified-Since |
比较资源的更新时间(与 If-Modified-Since 相反) |
Max-Forwards |
最大传输逐跳数 |
Proxy-Authorization |
代理服务器要求客户端的认证信息 |
Range |
实体的字节范围请求 |
Referer |
对请求中 URL 的原始获取方 |
TE |
传输编码的优先级 |
User-Agent |
HTTP 客户端程序的信息,代表的是客户端对应的操作系统和浏览器的版本信息。 |
Host字段是客户端发送请求时,用来指定服务器的域名的。
当客户端发起一个HTTP请求时,它需要知道请求应该发送到哪个服务器。Host头部字段提供了这个信息,它告诉服务器客户端希望与之交互的服务器的域名和端口号。对于直接连接到网站的服务器,Host头部字段通常包含服务器的域名。
但是,当客户端通过代理服务器发起请求时,情况就不同了。代理服务器可能会收到多个客户端的请求,并代表它们向不同的目标服务器发送请求。在这种情况下,客户端需要明确告诉代理服务器它希望代理服务器代表它向哪个目标服务器发送请求。因此,客户端在请求中包含Host头部字段,告诉代理服务器请求的目标服务器的域名和端口号。
Host头部字段的存在使得HTTP请求能够正确地路由到预期的服务器,无论是直接连接还是通过代理服务器。这是确保客户端和服务器之间通信能够准确无误地进行的必要步骤。
Referer用于标识当前请求的来源,即客户端之前访问的页面地址。
响应首部字段 (Response Header Fields):从服务器端向客户端返回响应报文时使用的首部。补充了响应的附加内容,也会要求客户端附加额外的内容信息。
首部字段名 | 说明 |
---|---|
Accept-Ranges |
是否接受字节范围请求 |
Age |
推算资源创建经过时间 |
ETag |
资源的匹配信息 |
Location |
令客户端重定向至指定 URL |
Proxy-Authenticate |
代理服务器对客户端的认证信息 |
Retry-After |
对再次发起请求的时机要求 |
Server |
HTTP 服务器的安装信息 |
Vary |
代理服务器缓存的管理信息 |
WWW-Authenticate |
服务器对客户端的认证信息 |
Location用于指示客户端重定向到一个新的URL。 它通常与状态码301(永久移动)或302(临时移动)一起使用,指示资源已被移动到新位置,并引导客户端自动请求新的URL。
实体首部字段 (Entity Header Fields):针对请求报文和响应报文的实体部分使用的首部。补充了资源内容更新时间等与实体有关的信息。
首部字段名 | 说明 |
---|---|
Allow |
资源可支持的 HTTP 方法 |
Content-Encoding |
实体主体适用的编码方式 |
Content-Language |
实体主体的自然语言 |
Content-Length |
实体主体的大小(单位:字节) |
Content-Location |
替代对应资源的 URI |
Content-MD5 |
实体主体的报文摘要 |
Content-Range |
实体主体的位置范围 |
Content-Type |
实体主体的媒体类型 |
Expires |
实体主体过期的日期时间 |
Last-Modified |
资源的最后修改日期时间 |
Content-Length:服务器在返回数据时,会有
Content-Length
字段,表明本次回应的数据长度。HTTP 是基于 TCP 传输协议进行通信的。TCP是一种面向流的协议,它不保证数据包的大小和顺序,因此在网络传输中可能会出现数据包被打包或拆包的情况,即"粘包"和"拆包"。HTTP 协议通过设置回车符、换行符作为 HTTP header 的边界,通过 Content-Length 字段作为 HTTP body 的边界,这两个方式都是为了解决"粘包"的问题。
为了解决这个问题,HTTP协议采用了以下两种方式:
HTTP Header的边界:HTTP协议使用回车符(\r)和换行符(\n)作为HTTP头部的边界。每个HTTP头部字段之间用空格分隔,字段值后面跟着一个换行符,最后一个字段后面跟着两个换行符,表示HTTP头部的结束。
HTTP Body的边界 :
Content-Length
头部字段用于指定HTTP响应体(Body)的长度。服务器在返回响应时,会根据Content-Length
字段值发送相应长度的数据。客户端收到数据后,可以根据Content-Length
字段值判断响应体的结束,从而解决"粘包"问题。Content-Length: 500
例如,如果
Content-Length
字段值为500,那么服务器会发送500个字节的数据作为响应体,客户端收到500个字节的数据后,就可以知道响应体的结束,不会再接收额外的数据。Content-Type:用于服务器回应时,告诉客户端,本次数据是什么格式。这对于客户端正确解析和显示响应体至关重要,因为不同的内容类型需要不同的解析方式。
- 内容类型 :
Content-Type
头部字段定义了响应体数据的MIME类型,这告诉客户端响应体的数据是以何种格式存储的。例如,text/html
表示响应体是HTML文档,image/jpeg
表示响应体是JPEG图片。- 字符集 :
Content-Type
头部字段还可以指定响应体使用的字符集,这对于文本数据尤为重要。例如,text/html; charset=UTF-8
表示响应体是HTML文档,并且使用UTF-8字符集。- 解析响应体 :客户端根据
Content-Type
头部字段的值来解析响应体。例如,如果响应体的Content-Type
是text/html
,客户端会将其解析为HTML文档并显示在浏览器中。- 缓存控制 :
Content-Type
头部字段还用于缓存控制,例如,如果响应体的Content-Type
是image/png
,客户端可能会将其缓存,并在后续请求中使用缓存版本。- 安全性和兼容性 :正确设置
Content-Type
头部字段可以提高安全性,因为它可以帮助客户端正确处理响应体,避免潜在的安全风险。同时,它也确保了客户端和服务器之间的兼容性。
这些首部字段在实际应用中能够极大地丰富HTTP报文的功能,使得通信更加灵活和高效。
五、HTTP cookie 与 session
HTTP 是无状态协议,它不对之前发生过的请求和响应的状态进行管理。也就是说,无法根据之前的状态进行本次的请求处理。假设要求登录认证的 Web 页面本身无法进行状态的管理(不记录已登录的状态),那么每次跳转新页面不是要再次登录,就是要在每次请求报文中附加参数来管理登录状态。
但是无状态协议当然也有它的优点。由于不必保存状态,自然可减少服务器的 CPU 及内存资源的消耗。从另一侧面来说,也正是因为 HTTP 协议本身是非常简单的,所以才会被应用在各种场景里。在保留无状态协议这个特征的同时又要解决类似的矛盾问题,于是引入了 Cookie 技术。Cookie 技术通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。
Cookie 会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie 的首部字段信息,通知客户端保存 Cookie。当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入 Cookie 值后发送出去。服务器端发现客户端发送过来的 Cookie 后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到之前的状态信息。
浏览器保存数据的方式:内存级和文件级。
内存级别的Cookie:
- 当一个cookie被设置而没有
Expires
或Max-Age
属性时,它被称为会话Cookie(session cookie)。这些cookie会存储在内存中,并且只在当前浏览器会话中有效。当浏览器关闭时,这些cookie会被删除。 - 因此,如果你关闭浏览器再重新打开,之前存储的会话Cookie会丢失,你可能需要重新登录。
文件级别的Cookie:
- 当一个cookie设置了
Expires
或Max-Age
属性时,它被称为持久Cookie(persistent cookie)。这些cookie会被存储在硬盘上的文件中,直到过期时间到达或者被显式删除。 - 这样,即使关闭浏览器或重启电脑,持久Cookie仍然会保存在硬盘上,允许你在再次访问网站时保持登录状态。
如果我们访问之前登录过的网站时需要重新输入账号和密码,说明之前保存的cookie可能是会话Cookie(内存级),因为会话Cookie在浏览器关闭时会被删除。
Cookie的首部字段
Cookie 的工作机制是用户识别及状态管理。Web 网站为了管理用户的状态会通过 Web 浏览器,把一些数据临时写入用户的计算机内。接着当用户访问该Web网站时,可通过通信方式取回之前发放的Cookie。调用 Cookie 时,由于可校验 Cookie 的有效期,以及发送方的域、路径、协议等信息,所以正规发布的 Cookie 内的数据不会因来自其他Web 站点和攻击者的攻击而泄露。
- 创建和存储Cookie
当用户首次访问某个Web网站时,服务器可以在HTTP响应中通过 Set-Cookie
头部向浏览器发送一个Cookie。例如:
http
HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: sessionId=abc123; Path=/; Expires=Wed, 09 Aug 2024 10:18:14 GMT; Secure; HttpOnly
浏览器接收到这个响应后,会将Cookie存储在用户的计算机内。存储的位置和方式取决于浏览器,但通常会保存在一个专门的文件或数据库中。
- 发送Cookie
在用户后续访问同一网站时,浏览器会自动在请求头中包含相应的Cookie。例如:
http
GET /page HTTP/1.1
Host: www.example.com
Cookie: sessionId=abc123
服务器接收到请求后,可以从请求头中读取Cookie并验证其内容,从而识别用户并恢复用户的状态。
首部字段 | 说明 | 首部类型 |
---|---|---|
Set-Cookie | 开始状态管理所使用的Cookie信息 | 响应首部类型 |
Cookie | 服务器接收到的Cookie信息 | 请求首部字段 |
首部字段 Cookie 会告知服务器,当客户端想获得 HTTP 状态管理支持时,就会在请求中包含从服务器接收到的 Cookie。接收到多个Cookie 时,同样可以以多个 Cookie 形式发送。服务器可以使用这些 Cookie 来识别客户端状态、保持会话、或管理用户信息等。
当服务器准备开始管理客户端的状态时,会事先告知各种信息。下面表格描述了 Set-Cookie
头部字段的常见属性及其详细信息:
属性 | 描述 | 默认值 | 示例 |
---|---|---|---|
Name=Value | Cookie的名称和值。由等号(=)分隔,名称和值之间没有空格。 | - | sessionId=abc123 |
Domain | 指定Cookie可用的域名。只有该域名及其子域名可以访问这个Cookie。 | 发出Cookie的域名 | Domain=example.com |
Path | 指定Cookie可用的路径。只有在这个路径或其子路径下的请求才会发送该Cookie。 | 发出Cookie的路径 | Path=/app |
Expires | 指定Cookie的过期时间,格式为HTTP日期(通常是GMT)。Cookie在此时间后失效。 | 浏览器会话结束时 | Expires=Wed, 09 Aug 2024 10:18:14 GMT |
Max-Age | 指定Cookie的有效期,以秒为单位,从设置Cookie的时间开始计算。与 Expires 互斥。 |
浏览器会话结束时 | Max-Age=3600 (1小时) |
Secure | 指定Cookie只能通过HTTPS连接发送。如果未设置,Cookie可以通过HTTP和HTTPS发送。 | - | Secure |
HttpOnly | 指定Cookie不能通过JavaScript访问,防止跨站脚本(XSS)攻击。启用后,客户端脚本无法访问这个Cookie。 | - | HttpOnly |
SameSite | 控制浏览器是否在跨站请求中发送Cookie,用于减少CSRF攻击的风险。 | 通常是 Lax ,但具体行为可能因浏览器而异 |
SameSite=Strict |
当服务器通过HTTP响应的 Set-Cookie
头来设置Cookie时,客户端会将该Cookie及其属性保存起来,并根据设置的属性(如过期时间、路径、域名等)来管理其存活。在随后的请求中,浏览器会将存储的Cookie中符合请求的属性(如路径和域名)自动附加到请求的 Cookie
头中。这个 Cookie
头中只包含Cookie的名称和值,不包括过期时间或其他属性。
下面我们举几个例子:
当服务器通过HTTP响应的
Set-Cookie
头来设置Cookie的过期时间时,响应头可能会包含如下信息:
httpSet-Cookie: sessionId=abc123; Path=/; Expires=Wed, 09 Aug 2024 10:18:14 GMT;
浏览器会根据
Set-Cookie
头部的信息将Cookie保存到本地。保存的信息包括:名称和值、过期时间 、路径。这样的话,当客户端(浏览器)发起后续请求时,浏览器会将存储的Cookie包含在HTTP请求的
Cookie
头中。例如:
httpGET /page HTTP/1.1 Cookie: sessionId=abc123
通过设置Cookie路径可以限制Cookie的作用范围,使其只在特定的路径下发送。通过指定路径,服务器可以控制Cookie在哪些请求中发送。以下是关于设置Cookie路径的详细说明:
在
Set-Cookie
头部中,可以使用Path
属性来设置Cookie的路径。例如:
httpSet-Cookie: sessionId=abc123; Path=/example/path; Expires=Wed, 09 Aug 2024 10:18:14 GMT; Secure; HttpOnly
这里,
Path=/example/path
指定了Cookie的路径。路径的作用
- 全局路径 :
Path=/
表示Cookie适用于整个网站。- 特定路径 :
Path=/example/path
表示Cookie只会在请求以/example/path
开头的路径时发送。
全局路径
httpSet-Cookie: sessionId=abc123; Path=/; Expires=Wed, 09 Aug 2024 10:18:14 GMT; Secure; HttpOnly
- 这个Cookie会在网站的所有请求中发送,无论请求的路径是什么。
特定路径
httpSet-Cookie: sessionId=abc123; Path=/user; Expires=Wed, 09 Aug 2024 10:18:14 GMT; Secure; HttpOnly
- 这个Cookie只会在请求以
/user
开头的路径时发送,比如/user/profile
或/user/settings
。假设服务器在响应中设置了以下Cookie:
httpSet-Cookie: userToken=xyz789; Path=/account; Expires=Wed, 09 Aug 2024 10:18:14 GMT; Secure; HttpOnly
客户端发起的请求:
请求路径
/account/login
httpGET /account/login HTTP/1.1 Host: www.example.com Cookie: userToken=xyz789
userToken
Cookie 会被发送,因为请求路径匹配/account
。请求路径
/profile
httpGET /profile HTTP/1.1 Host: www.example.com
userToken
Cookie 不会被发送,因为请求路径不匹配/account
。
- Path属性 :通过在
Set-Cookie
头部中设置Path
属性,可以限制Cookie的作用范围。- 全局路径 :
Path=/
适用于整个网站。- 特定路径 :
Path=/example/path
只适用于以指定路径开头的请求。这种机制允许服务器更灵活地控制Cookie的使用范围,提高了安全性和效率。
那么如何提交两个Cookie呢?
在HTTP请求中提交多个Cookie时,可以在请求头中的
Cookie
头部列出所有要发送的Cookie,每个Cookie之间用分号和空格分隔。以下是如何在HTTP请求中提交两个Cookie的示例。首先,服务器通过HTTP响应头中的
Set-Cookie
头部设置多个Cookie。例如:
httpHTTP/1.1 200 OK Content-Type: text/html Set-Cookie: sessionId=abc123; Path=/; Expires=Wed, 09 Aug 2024 10:18:14 GMT; Secure; HttpOnly Set-Cookie: userToken=xyz789; Path=/; Expires=Wed, 09 Aug 2024 10:18:14 GMT; Secure; HttpOnly
客户端发送多个Cookie:
客户端在后续请求中可以在
Cookie
头部中包含多个Cookie,每个Cookie之间用分号和空格分隔。例如:
httpGET /some-page HTTP/1.1 Host: www.example.com Cookie: sessionId=abc123; userToken=xyz789
服务器设置多个Cookie :通过多个
Set-Cookie
头部设置。客户端发送多个Cookie :在
Cookie
头部中列出所有Cookie,每个Cookie之间用分号和空格分隔。
但是如果我们仅使用Cookie的话,由于Cookie 存储在客户端,容易被篡改、盗用或劫持。如果所有的状态信息(尤其是敏感数据,如用户身份信息或权限)都存储在Cookie中,可能会暴露给恶意用户。此时我们引出 Session。
Session 是一种在Web应用程序中用于存储用户信息的机制。它允许服务器在多个请求之间保持对用户的了解。当用户首次访问一个Web应用程序时,服务器可能会为该用户创建一个Session,并为其分配一个唯一的Session ID。然后,在随后的请求中,服务器可以通过检查Session ID来识别用户,并从Session中获取用户的偏好、信息或其他相关数据。与Cookie相比,Session的主要区别在于:
- Session是服务器端的,而Cookie是客户端的。这意味着Session存储在服务器的内存或数据库中,而Cookie存储在用户的计算机上。
- Session通常具有更短的生命周期。一旦用户关闭了浏览器或超出了Session的有效期,Session就会结束,服务器会删除相关的信息。而Cookie可以有较长的生命周期,即使用户关闭了浏览器,Cookie仍然保存在用户的计算机上,直到过期或被用户删除。
- Session不支持跨域共享。也就是说,在一个域内创建的Session不能在另一个域中使用。而Cookie支持跨域共享,可以在不同的域之间传递信息。
- Session比Cookie更安全。因为Session存储在服务器端,不容易受到攻击者的篡改或窃取。而Cookie存储在用户的计算机上,可能更容易受到攻击者的威胁。
简单来说,Session主要用于在多个请求之间保持用户信息,而Cookie则用于存储用户的偏好和身份验证信息。
使用Session的步骤如上图所示。Session ID是一个唯一标识符,用于区分不同的用户会话。它可以被视为一种"等于号",将特定的用户与他们在服务器上的会话数据关联起来。
然而,如果 Session ID 被第三方盗走,对方就可以伪装成你的身份进行恶意操作了。因此必须防止 Session ID 被盗,或被猜出。为了做到这点,Session ID 应使用难以推测的字符串,且服务器端也需要进行有效期的管理,保证其安全性。
HTTP报头的通用首部字段的
Cache-Control
与Cookie的Expires
有联系吗?
Cache-Control
是一个HTTP响应头部字段,用于指定浏览器或其他中间缓存(如代理服务器、CDN)应该如何处理资源的缓存。而Expires
是一个Cookie属性,用于指定Cookie的有效期。
Cache-Control
确定的是资源的缓存有效期,而 Expires
确定的是Cookie的有效期。如果 HTTP 响应头部同时有 Cache-Control
和 Expires
字段的话,Cache-Control 的优先级高于 Expires 。