网络协议-HTTP协议详解-HTTP报文首部字段

HTTP 协议的请求和响应报文中必定包含 HTTP 首部,首部内容为客户端和服务器分别处理请求和响应提供所需要的信息,对于客户端普通用户来说,这些信息中的大部分内容都无须亲自查看。

而 HTTP 报文首部又分为起始行和首部字段两部分,请求报文的起始行包含 HTTP 请求方法、URL资源、客户端 HTTP 协议版本,响应报文的起始行包含服务器 HTTP 协议版本、状态码和原因短语,这些东西学院君在前面的分享中都已经介绍过,今天我们来看首部字段。

HTTP 首部字段是构成 HTTP 报文的要素之一,在客户端与服务器之间以 HTTP 协议进行通信的过程中,无论是请求还是响应都会使用首部字段,它能起到传递额外重要信息的作用,比如报文主体大小、所使用的语言、认证信息、是否缓存、Cookie 等。

首部字段结构及分类

首部字段由字段名和字段值两部分构成,中间用冒号分隔,比如下面这种:

Connection: keep-alive

另外,单个 HTTP 首部字段可以有多个值,不同值之间通过逗号分隔:

Accept-Encoding: gzip, deflate

有些首部字段只能在请求报文中使用,有些首部字段只能在响应报文中使用,有些则既可以在请求报文中使用,又可以在响应报文中使用,基于使用场景可以将首部报文分为以下五类:

  • 通用首部字段:请求报文和响应报文都可以使用的首部字段;
  • 请求首部字段:从客户端向服务器发送请求报文时使用的首部字段;
  • 响应首部字段:从服务器端向向客户端返回响应报文时使用的首部字段;
  • 实体首部字段:针对请求报文和响应报文的实体部分使用的首部字段;
  • 扩展首部字段:非 HTTP 协议标准规定的首部字段,通常由开发者创建,用于某些特殊用途,比如 Cookie、Set-Cookie。

通用首部

常见的通用首部字段如下表所示:

下面我们来详细介绍每个通用首部字段的使用。

Cache-Control

通过指定首部 Cache-Control 字段的指令值就能操作 HTTP 缓存的工作机制。

在请求报文首部,Cache-Control 可以包含以下指令:

在响应报文首部,Cache-Control 可以包含以下指令:

后面我们会结合 Cache-Control 与其他缓存相关首部字段(Expires、If-Modified-Since、Last-Modified、If-None-Match、Etag 等)介绍 HTTP 缓存的完整解决方案,这里先了解下其功能及指令即可。

Connection

Connection 首部字段的作用主要有两个:

  • 在客户端发送请求和服务器返回响应时,将 Connection 首部字段值设置为 Upgrade 可控制不再转发给代理的首部字段;
  • 可以通过设置该字段值为 keep-alive 来建立持久连接(HTTP/1.1 版本默认都是持久连接),客户端会在持久连接上连续发送请求;当服务器端想明确断开连接时,则指定 Connection 首部字段为 close。

Date

该字段用于标识创建 HTTP 报文的日期和时间。

HTTP/1.1 协议使用在 RFC1123 中规定的日期时间的格式:

Date: Fri, 19 Apr 2019 02:57:46 GMT

Pragma

Pragma 是 HTTP/1.1 之前版本的历史遗留字段,仅作为与 HTTP/1.0 的向后兼容而定义:

Pragma: no-cache

HTTP/1.1 中使用 Cache-Control: no-cache 来替代该字段的功能。

Trailer

该字段用于事先说明在报文主体后记录了哪些首部字段,可应用于 HTTP/1.1 版本的分块传输编码。

Transfer-Encoding

该首部字段规定了传输报文主体时采用的编码方式:

Transfer-Encoding: chunked

HTTP/1.1 版本的传输编码方式仅对分块传输编码有效。

Upgrade

用于检测 HTTP 协议及其他协议是否可使用更高的版本进行通信,其参数值可以用来指定一个完全不同的通信协议。

Via

该字段用于追踪客户端与服务器之间的请求和响应报文的传输路径(关于这一点我们在前面介绍 TRACE 请求方法时提到过)。报文经过代理或网关时,会先在首部字段 Via 中附加该服务器的信息,然后再进行转发。

此外,首部字段 Via 不仅可用于追踪报文的转发,还可以避免请求回环的发生。

Warning

该字段从 HTTP/1.0 的响应首部字段 Retry-After 演变而来,通常会告知用户一些与缓存相关的问题的警告。

HTTP/1.1 定义了 7 种警告:

在通用首部中,比较值得关注的首部字段就是 Cache-Control 和 Connection,Connection 相对简单,在 HTTP/1.1 协议中,一般都是默认值 keep-alive,Cache-Control 相对复杂,指令值也很多,后面我们在介绍 HTTP 缓存实现机制与原理的时候会详细介绍该首部字段的使用。

请求首部

常见的请求首部字段,如下表所示:

请求首部字段是从客户端往服务器端发送请求报文时所使用的首部字段,用于补充请求的附加信息、客户端信息、对响应内容相关的优先级等内容。下面我们来简单介绍下每个请求首部字段的用途和注意事项。

Accept

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3

该字段用于告知服务器用户代理(即客户端浏览器)能够处理的媒体类型及媒体类型的相对优先级。这些媒体类型都是 MIME 类型:

  • 文本文件:text/html、text/plain、text/css、application/json...
  • 图片文件:image/jpeg、image/gif、image/png...
  • 视频文件:video/mpeg、video/quicktime...
  • 应用程序使用的二进制文件:application/octet-stream、application/zip...

若想要给显示的媒体类型增加优先级,可以使用 q= 来额外表示权重值(0~1,默认值是 1.0),并用分号进行分隔。当服务器提供多种内容时,将会首选返回权重值最高的媒体类型。

Accept-Charset

该字段用来告知服务器用户代理支持的字符集及字符集的相对优先顺序。用法和 Accept 类似:

Accept-Charset: utf-8,iso-8859-1;q=0.5

Accept-Encoding

Accept-Encoding: gzip, deflate, br

该字段用来告知服务器用户代理支持的内容编码及内容编码的优先级顺序。常见的内容编码如下:

  • gzip:由文件压缩程序 gzip(GNU zip)生成的编码格式(RFC1952),采用 Lempel-Ziv 算法及 32 位循环冗余校验(CRC);
  • compress:由 UNIX 文件压缩程序 compress 生成的编码格式,采用 Lempel-Ziv-Welch 算法;
  • deflate:组合使用 zlib 格式(RFC1950)及由 deflate 压缩算法(RFC1951)生成的编码格式;
  • br:表示采用 Brotli 算法的编码方式;
  • identify:不执行压缩或不会变化的默认编码格式。

Accept-Language

用来告知服务器用户代理能够处理的自然语言集,以及自然语言集的相对优先级,用法和 Accept 字段类似:

Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7

Authorization

用来告知服务器用户代理的认证信息。通常,想要通过服务器认证的用户代理会在接收到返回的 401 状态码响应后,把首部字段 Authorization 加入请求,比如我们使用 Laravel 框架自带的 HTTP 基本认证进行认证后就可以在后续请求首部中看到这个字段:

有关 HTTP 访问认证及 Authorization 首部字段后面介绍 HTTP 认证时会详细说明。

Expect

该字段用于告知服务器期望出现的某种特定行为,因服务器无法理解客户端的期望作出回应而发生错误时,会返回状态码 417 Expectation Failed

客户端可以利用该首部字段写明所期望的扩展,虽然 HTTP/1.1 规范只定义了 100-continue。这个字段平时很少用到。

From

该字段用于告知服务器使用用户代理的用户的电子邮件地址,通常,其使用目的就是为了显示搜索引擎等用户代理的负责人的电子邮件联系方式。这个字段日常也很少用到。

Host

Host: laravelacademy.org

该字段用于告知服务器请求的资源所处的互联网主机名和端口号。该字段在 HTTP/1.1 规范内是唯一一个必须包含在请求内的首部字段,因为请求行里的 URL 资源通常是相对 URL,需要结合 Host 字段才能拼接出完整的 URL,对于一台 Web 服务器上通常部署了多个站点的情况(我们通常称之为虚拟主机),Host 必须是域名而不能是 IP 地址,Web 服务器会根据这个 Host 字段值将请求指向对应域名指定的配置目录。

If-Match

形如 If-XXX 这种样式的请求首部字段,都可称为条件请求,服务器收到附带条件的请求后,只有判断指定条件为真时,才会执行请求,常用于实现缓存相关功能。

首部字段 If-Match 属于附带条件之一,它会告知服务器匹配资源所用的实体标记(ETag)值,这时的服务器无法使用弱 ETag 值(以 W/ 开头)。

服务器会对比 If-Match 字段值和资源的 ETag 值,仅当两者一致时,才会执行请求,反之,则返回状态码 412 Precondition Failed 响应。

还可以使用星号 * 指定 If-Match 的字段值,针对这种情况,服务器将会忽略 ETag 的值,只要资源存在就处理请求。

If-None-Match

该字段和 If-Match 作用相反,用于指定 If-None-Match 字段值的实体标记(ETag)值与请求资源的 ETag 不一致时,它就告知服务器处理该请求。

在 GET 或 HEAD 方法中使用请求首部字段 If-None-Match 可获取最新的资源。

If-Modified-Since

该字段会告知服务器若 If-Modified-Since 字段值早于资源的更新时间,则希望能够处理该请求。反之则返回状态码 304 Not Modified 响应。

If-Modified-Since 用于确认代理或客户端拥有的本地资源的有效性。资源的最近更新日期时间,可以通过响应首部字段 Last-Modified 来获取。

If-Unmodified-Since

和 If-Modified-Since 作用相反。告知服务器指定的请求资源只有在字段值内指定的日期时间之后未发生更新的情况下,才能处理请求。否则以状态码 412 Precondition Failed 作为响应返回。

If-Range

该字段用于告知告知服务器若指定的 If-Range 字段值(ETag 值或时间)和请求资源的 ETag 值或时间相一致,则作为范围请求处理,否则返回全体资源。

Max-Forwards

前面我们在介绍 HTTP 请求方法时提到过,通过 TRACE 方法或 OPTIONS 方法发送包含首部字段 Max-Forwards 的请求时,该字段以十进制整数形式指定可经过的服务器最大数目。服务器在往下一个服务器转发请求之前,Max-Forwards 的值减1后重新赋值。当服务器接收到 Max-Forwards 值为 0 的请求时,不再进行转发,而是直接返回响应。

Proxy-Authorization

接收到从代理服务器发来的认证质询时,客户端会发送包含首部字段 Proxy-Authorization 的请求,以告知服务器认证所需要的信息。该行为和客户端与服务器之间的 HTTP 访问认证相似(对应的首部字段是 Authorization),不过认证行为是发生在客户端与代理之间。

Range

对于只需要获取部分资源的范围请求,包含首部字段 Range 即可告知服务器资源的指定范围。

接收到附带 Range 首部字段请求的服务器,会在处理请求之后返回状态码 206 Partial Content 的响应。无法处理该范围请求时,则会返回状态码 200 OK 的响应及全部资源。

Referer

该字段用于告知服务器当前请求的上一个请求对应资源的 URL:

Referer: https://laravelacademy.org/laravel-docs-5_8

客户端一般都会发送 Referer 首部字段给服务器,但当直接在浏览器地址栏输入 URL 时,出于安全考虑,可以不发送该首部字段。

Referer 的正确拼写应该是 Referrer,但不知为何,大家都沿用了这个错误的拼写。

TE

该字段用于告知服务器客户端能够处理响应的传输编码方式及相对优先级,和首部字段 Accept-Encoding 的功能类似,所以一般很少见。

除了指定传输编码外,还可以指定伴随 Trailer 字段分块传输编码的方式,应用后者时,只需把 trailers 赋值该该字段即可。

User-Agent

该字段会将创建请求的浏览器和用户代理名称等信息传达给服务器:

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36

响应首部

常见的响应首部字段,如下表所示::

响应首部字段是由服务器端向客户端返回响应报文中所使用的字段,用于补充响应的附加信息、服务器信息、以及对客户端的附加要求等信息。下面我们来简单介绍下每个请求首部字段的用途和注意事项。

Accept-Ranges

该字段用来告知客户端服务器是否能处理范围请求,以指定获取服务器端某个部分的资源。可指定的字段值有两种,可处理范围请求时指定其为 bytes,反之指定其为 none。

Age

该字段用于告知客户端源服务器在多久前创建了响应,字段值的单位为秒。若创建该响应的服务器是缓存服务器,Age 值是指缓存后的响应再次发起认证到认证完成的时间值,代理创建响应时必须加上首部字段 Age。

ETag

该字段用于告知客户端服务器资源的实体标识,它是一种可将资源以字符串做唯一性标识的方式。服务器会为每份资源分配对应的 ETag 值。

另外,当资源更新时,ETag 值也需要更新,生成 ETag 值时,并没有统一的算法规则,而仅仅是由服务器来分配。后续介绍 HTTP 缓存时会详细介绍该字段。

ETag 字段值有强弱之分:

  • 强 ETag 值:不论实体发生多么细微的变化都会改变其值;
  • 弱 ETag 值:只用于提示资源是否相同,只有资源发生了根本变化,产生差异时才会改变 ETag 值,这时,会在字段值开头附加 W/,例如:ETag: W/"usagi-1234"

Location

该字段可以将响应接收方引导至某个与请求 URL 位置不同的资源。通常,该字段会配合 3XX:Redirection 响应,提供重定向的 URL,如下图所示:

几乎所有浏览器在接收到包含首部字段 Location 的响应后,都会强制性地尝试对已提示的重定向资源的访问。

Proxy-Authenticate

该字段会把由代理服务器所要求的认证信息发送给客户端。它与客户端和服务器之间的 HTTP 访问认证的行为相似,不同之处在于其认证行为是在客户端与代理之间进行的,而客户端与服务器之间进行认证时,首部字段 WWW-Authorization 有着相同的作用。

Retry-After

该字段用于告知客户端应该在多久之后再次发送请求,主要配合状态码 503 Service Unavailable 响应,或 3XX Redirect 响应一起使用。字段值可以是具体的日期时间,也就是创建响应后的秒数,比如我们在 Laravel 中定义一个 302 重定向路由如下:

Route::get('/redirect', function () {
    return redirect('https://laravelacademy.org', 302, [
        'Retry-After' => 30
    ]);
});

我们在响应首部(响应头)中添加了 Retry-After 字段,这样就可以在响应报文中看到该字:

Server

该字段用于告知客户端当前服务器上安装的 HTTP 服务器应用程序的信息,字段值中不仅会标出 HTTP 服务器软件应用名称,还会包含版本号和安装时启用的可选项:

Server: nginx/1.12.0

要隐藏或修改该字段,需要修改并重新编译相应的 HTTP 服务器软件源码。

Vary

该字段可对缓存进行控制,源服务器会向代理服务器传达关于本地缓存使用方法的命令。从代理服务器接收到源服务器返回包含 Vary 指定项的响应之后,若再要进行缓存,仅对请求中含有相同 Vary 指定首部字段的请求返回缓存。

WWW-Authenticate

该字段用于 HTTP 访问认证,它会告知客户端适用于访问请求 URL 所指定资源的认证方案(Basic 或 Digest)和带参数提示的质询。状态码 401 Unauthorized 响应中,肯定带有首部字段 WWW-Authenticate:

在后续介绍 HTTP 认证时还会结合 Authenticate 首部字段详细介绍该字段的使用明细。

实体首部

常见的实体首部字段如下表所示:

实体首部字段是包含在请求报文和响应报文中实体部分所使用的首部,用于补充内容的更新时间等与实体相关的信息。

Allow

该字段我们在前面介绍 OPTIONS 请求方法时提到过,用于通知客户端能够服务器针对 Request URL 指定资源能够支持的所有 HTTP 请求方法,当服务器接收到不支持的 HTTP 方法时,会以状态码 405 Method Not Allowed 作为响应返回,与此同时还会把所有能支持的 HTTP 方法写入首部字段 Allow 后返回。

Content-Encoding

Content-Encoding: gzip

该字段用于告知客户端服务器对实体的主体部分选用的内容编码方式(一般都是数据压缩方式)。主要有以下几种内容编码方式:

  • gzip
  • compress
  • deflate
  • br
  • identify

这些内容编码方式在介绍 Accept-Encoding 首部字段时已经提到过,这里不再赘述。Accept-Encoding 一般用于客户端在发起请求时声明自己可以支持的内容编码方式,通过该请求首部字段与服务器进行协商,然后服务器在 Content-Encoding 响应首部提供了实际采用的内容编码方式。

需要注意的是,服务器端并不强制要求一定使用哪种内容编码方式。具体采用哪种内容编码方式高度依赖于服务器端的设置,及其所采用的模块,比如 Nginx 配置文件的 http 模块配置块中有如下配置项:

gzip on;
gzip_disable "msie6";

表示 Nginx 服务器在处理 HTTP 请求时启用 gzip 格式编码,但是在 IE6 中会禁用此编码。

讲到这里我们还要澄清 Transfer-Encoding 与 Content-Encoding 之间的区别,前面我们讲到 Transfer-Encoding 也是用于指定报文主体传输编码方式,但是它是逐跳首部,即只在两个相邻节点间有效,它跟前面介绍的 TE 首部字段是一对,TE 也是逐跳首部,用于告知服务器客户端能够处理的编码方式和相对优先级,而 Content-Encoding 和 Accept-Encoding 是一对,都是端到端首部,在整个传输过程中有效。

为了解释清楚这个过程,我们举例来说明:

假设 A 为服务器,D 为客户端,从 A 到 D 的路径为 A-B-C-D(B、C 为中间节点,比如代理),所需传输的资源为 X。步骤如下:

(1)D 向 A 请求 X,并在请求报文中指明自己支持的编码方式为 gzip:

Accept-Encoding: gzip

(2)请求按路径传递到 A 处,A 将 X 用 gzip 编码进行压缩并发到 B 处,由 B 进行下一步转交,并在报文中指明使用的编码方式为 gzip;

Content-Encoding: gzip

(3)B 认为传给 C 时使用分块传输比较合理,就对 A 传过来的报文实体进行分块,并在报文中说明:

Content-Encoding: gzip
Transfer-Encoding: chunked

(4)C 收到 B 的报文,并根据 Transfer-Encoding: chunked 判断出 B 进行了分块传输,于是 C 对收到的各个分块进行重组,还原出完整的 X(注意此时的 X 还是被 gzip 压缩过的状态)。之后 C 不进行分块,直接将整个发送给 D:

Content-Encoding: gzip

(5)D 接收到响应报文,并根据 Content-Encoding: gzip 判断出报文实体已经被 gzip 压缩过了,于是对其进行解码,最终获得资源 X。

Content-Language

该字段用于告知客户端实体主体使用的自然语言。

与之类似的还有一个 Accept-Language 请求首部字段,该字段也是客户端发起请求时声明的可以理解的自然语言,用于与服务器进行协商,然后服务器可以通过 Content-Language 告知协商结果,如果没有指明 Content-Language,那么默认地,文件内容是提供给所有语言的访问者使用的。

Content-Length

该字段表明实体主体部分的大小(单位是字节),对实体主体进行分块内容编码传输时,不能再使用 Content-Length 首部字段,即使用了 Transfer-Encoding: chunked 编码,否则其他情况下必须在响应首部中包含此字段。

Content-Location

该字段用于给出与报文主体部分相对应的 URL,和首部字段 Location 不同,Content-Location 表示的是报文主体返回资源对应的 URL。

Content-MD5

该字段用于检查报文主体在传输过程中是否保持完整,以及确认传输到达。

其实现过程如下:对报文主体执行 MD5 算法得到 128 位二进制数,再通过普通 Base64 编码后将结果写入 Content-MD5 字段值(由于 HTTP 首部无法记录二进制值,所以要通过 Base64 编码处理)。

但采用这种方法,对内容上偶发性改变无从查证,也无法检测出恶意篡改。因为内容如果能篡改,那么意味着 Content-MD5 值也可重新计算然后被篡改,所以处在接收阶段的客户端是无法意识到报文主体以及首部字段 Content-MD5 是已经被篡改的。

Content-Range

针对范围请求,在响应首部中使用该字段能告知客户端作为响应返回的实体的哪个部分符合范围请求,字段值以字节为单位,表示当前发送部分及整个实体大小:

Content-Range: bytes 5001-10000/10000

Content-Type

该字段表示实体主体内对象的媒体类型,和首部字段 Accept 一样,字段值用 type/subtype 形式赋值

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

显然,该字段和请求首部字段 Accept 是一对,Accept 字段用于客户端在发起请求时告知服务器自己能够处理的内容类型,以便和服务器进行协商,服务器则通过 Content-Type 响应首部字段告知客户端协商结果。

Expires

该字段将资源失效日期告知客户端,缓存服务器在接收到含有首部字段 Expires 的响应后,会以缓存来应答请求,在 Expires 字段值指定的时间之前,响应的副本会一直保存。当超过指定时间后,缓存服务器在请求发送过来时,会转向源服务器请求资源。

当首部字段 Cache-Control 有指定 max-age 指令时,比起首部字段 Expires,会优先处理 max-age 指令。后面我们介绍 HTTP 缓存时,还会继续介绍该首部字段。

Last-Modified

该字段指明资源最新修改的时间,一般来说,这个值就是请求 URL 指定资源被修改的时间。常常与 If-Modified-Since 字段结合使用,后面我们在介绍 HTTP 缓存时还会详细介绍该字段。

补充介绍:端到端首部与逐跳首部

HTTP 首部字段根据作用范围可以分为两种类型:

  • 端到端首部:该类型首部字段会转发给请求或响应对应的最终接收目标,且必须保存在中间节点(代理或缓存)生成的响应中,并规定它必须被转发。
  • 逐跳首部:该类型首部字段只对单次转发有效(即相邻两个节点的 HTTP 通信),会因通过缓存或代理等中间节点而不再转发。HTTP/1.1 及之后版本中,如果要使用逐条首部,需提供 Connection 首部字段。

下面列举了 HTTP/1.1 中的逐跳首部,除此之外其它所有字段都属于端到端首部:

  • Connection
  • Keep-Alive
  • Proxy-Authenticate
  • Proxy-Authorization
  • Trailer
  • TE
  • Transfer-Encoding
  • Upgrade

扩展字段

除了前面介绍的通用首部字段、请求首部字段、响应首部字段和实体首部字段之外,还有一类首部字段叫做扩展首部字段,而在扩展首部字段中,最有名的自然是 Cookie 相关首部字段,这篇教程学院君将重点介绍 Cookie 相关首部字段。

管理服务器与客户端之间状态的 Cookie,虽然没有被编入标准化 HTTP/1.1 的 RFC2616 中,但在 Web 网站得到了广泛的应用。

由于 HTTP 协议本身是无状态的,引入 Cookie 的初衷就是实现客户端用户识别和状态管理。Web 网站为了管理用户的状态,通过浏览器把一些数据临时写入用户的计算机内,然后当用户继续访问该网站时,可通过通信方式取回之前发放的 Cookie,这样一来服务器就可以通过 Cookie「识别」该客户端。

从安全性上说,调用 Cookie 时,由于可以校验 Cookie 的有效期,以及发送方的域(Domain)、路径(URL Path)、协议等信息,所以正规发布的 Cookie 内的数据不会因来自其它 Web 站点和攻击者的攻击而泄露。

日常使用的 Cookie 首部字段主要是以下两个

该字段用于响应首部,服务器通过该字段将需要设置的 Cookie 信息告知客户端,客户端接收到响应后将相应的 Cookie 信息存储到本地,以 Laravel 项目为例,默认的 Set-Cookie 字段及对应字段值如下所示:

Set-Cookie: laravel_session=eyJpdiI6InpDTWIxczdmK2hJZ1hPcWVsRU9uRUE9PSIsInZhbHVlIjoib244YVppNWFWdU04K3kxT3pUM3FmTWVqNkYxQXo3QUJHRzV0OWZnOEE1TzZKZGxxNHlpaXZnNlwvYzRrZ0RcL1lrIiwibWFjIjoiODZlZDgzNzlmNmNkZTJhNGFmNThmYTE2NGYxMTIyM2EwNGY5ZThkZmQ5MDU0NWQ0ZTJlY2M1ZTJmNjJmNDIzMiJ9; expires=Wed, 24-Apr-2019 04:03:23 GMT; Max-Age=7200; path=/; httponly

在该字段中,我们可以设置多个属性,每个属性间通过分号分隔。

第一个属性通常是 Cookie 名称及对应值,比如这里的 laravel_session 是 Session ID,该属性用于实现基于 Cookie 的 Session 认证,我们在客户端及服务器可以通过 laravel_session 字段获取对应的 Cookie 值。

后面其它的属性则是描述该 Cookie 的其它附加属性,这些附加属性对所有 Cookie 来说都是通用的:

  • expires:指定 Cookie 的有效期,省略的话默认在浏览器会话时间内有效(浏览器关闭失效),Cookie 一旦发送至客户端,就不能在服务器端显式删除,只能通过覆盖实现对客户端 Cookie 的「删除」;
  • Max-Age:和 expires 作用类似,用于指定从现在开始该 Cookie 存在的秒数,如果同时指定了 expires 和 Max-Age,那么 Max-Age 的值将优先生效;
  • path:指定 Cookie 生效的路径,默认路径是根路径 /;
  • domain:指定 Cookie 所属的域名,省略的话默认是当前域名,Cookie 只有在所属域名下才能获取,不能跨域名获取 Cookie,比如在 laravelacademy.org 对应应用下生成的 Cookie 所属域名是 laravelacademy.org,对应 Cookie 只能在 laravelacademy.org 域名应用下获取,在 blog.laravelacademy.org 对应应用下生成的 Cookie 所属域名是 blog.laravelacademy.org,对应 Cookie 只能在 blog.laravelacademy.org 域名应用下获取,依次类推。我们还可以通过通配符在生成 Cookie 时指定所属域名为 *.laravelacademy.org,这样一来,不管是 laravelacademy.org 还是 blog.laravelacademy.org,都可以获取到相应的 Cookie;
  • secure:限制浏览器只有在页面启用 HTTPS 安全连接时才可以发送 Cookie,省略的话,无论 HTTP 还是 HTTPS 都可以发送;
  • httponly:是 Cookie 的扩展功能,使 JavaScript 无法获取 Cookie,主要目的是为了防止跨站脚本攻击(XSS)对 Cookie 信息的窃取。

如果服务器设置了多个 Cookie,那么响应首部中会包含多个 Set-Cookie 首部字段:

2)Cookie

该字段用于请求首部,客户端通过该字段告知服务器当客户端想要获取 HTTP 状态管理支持时,就会在请求中包含从服务器接收到的 Cookie:

Cookie: hello=eyJpdiI6IktlV2RlQUhnbDBJN2Z0UUhFSHl3bkE9PSIsInZhbHVlIjoieElBdFpOV3crNm5IZytnRzlJUW1LUT09IiwibWFjIjoiNzFiZGEzMzg1MzgyYTMyYjM0YzcyNTViZWU2NGI2MDM2NzJhMGEwNmFkYWE5ZGY4N2I5ZDA4ZWQ0NmVkZjcyOCJ9; XSRF-TOKEN=eyJpdiI6IndOeWNWVmxXVEdpZkdlWFFkMENtckE9PSIsInZhbHVlIjoiYWJNb28yMlROWE1YOEVyTnhrbmJwYjRpdHB3S2diUDBcLzI2d1ViNXpRYkxzb2pMZEZWVll0cVFoejhlNG1jdEwiLCJtYWMiOiI1NzUwMWRjYzhjMjAwMDkwMWI4NDY0ZTIzMzY2NDYwMDY1NmYzZmMyOTA3ZjM2YTRmN2FmM2U1OGU3MWQyNTVkIn0%3D; laravel_session=eyJpdiI6ImpwcWx6SGttbUlCU2dCREVyRWp1WFE9PSIsInZhbHVlIjoiU0djd0Vjc3JRZzNuWUgyUWlRSStiUURcL2RPWFpxdjBjdXRrdVRjZ1hzdDZpTGNzZWtKNXpVTTJlXC9Fbms3ZWpqIiwibWFjIjoiMmI0NmJiZWYyOGViOGI5ZDVhY2EwMjI4NjAwODYwMzg1ZGZlODY0NjExNzIzMjczMGRiMjdjNDIyMTdiNzQ1MCJ9

可以看到,该 Cookie 请求首部字段中包含了上一步从服务器响应首部中获取到的所有 Cookie。

原文地址:https://www.cnblogs.com/stringarray/p/12989549.html