第七章 Cookie相关和其他的首部字段
最后更新于:2022-04-02 04:41:25
# 第七章 为 Cookie 服务和其他首部字段
> 作者:肖鹏-SpiritLing 时间:2019-01-30
> 包含 为 `Cookie` 服务的首部字段和其他首部字段
## 第一节 为 Cookie 服务的首部字段
管理服务器与客户端之间状态的 `Cookie` ,虽然没有被编入标准化 HTTP/1.1 的 RFC2616 中,但在 Web 网站方面得到广泛的应用。
`Cookie` 的工作机制是用户识别及状态管理。web 网站为了管理用户的状态会通过 web 游览器,把一些数据临时写入用户的计算机内。接着当用户访问该 web 网站时,可通过通信方式取回之前存放的 `Cookie` 。
调用 `Cookie` 时,由于可校验 `Cookie` 的有效期,以及发送方的域、路径、协议等信息,所以正规发布的 `Cookie` 内的数据不会因来自其他 web 站点和攻击者的攻击而泄露。
在目前使用最广泛的 `Cookie` 标准却不是 RFC 中定义的任何一个。而是在网景公司指定的标准上进行扩展后的产物。
下面是与 `Cookie` 有关的首部字段
| 首部字段名 | 说明 | 首部类型 |
| --- | --- | --- |
| Set-Cookie | 开始状态管理所使用的 `Cookie` 信息 | 响应首部字段 |
| Cookie | 服务器接收到的 `Cookie` 信息 | 请求首部字段 |
### 第一小节 Set-Cookie 字段
```http
Set-Cookie: status-enable; expires=Tue, 05 Jul 2018 02:01:22 GMT; path=/; domain=.example.com;
```
当服务器准备开始管理客户端的状态时,会事先告知各种信息。下面表格列举了 `Set-Cookie` 的字段值。
| 属性 | 说明 |
| --- | --- |
| NAME=VALUE | 赋予 `Cookie` 的名称和其值(必须项) |
| expires=DATE | `Cookie` 的有效期(若不明确指定则默认为游览器关闭前为止) |
| path=PATH | 将服务器上的文件目录作为 `Cookie` 的适用对象(若不指定则默认文档所在的文件目录) |
| domain=域名 | 作为 `Cookie` 适用对象的域名(若不指定则默认为创建 `Cookie` 的服务器域名) |
| Secure | 仅在 HTTPS 安全通信时才会发送 `Cookie` |
| HttpOnly | 加以限制,使 `Cookie` 不能被 JavaScript 脚本访问 |
* **expires 属性**
`Cookie` 的 `expires` 属性指定游览器可发送 `Cookie` 的有效期。
当省略 `expires` 属性时,其有效期仅限于维持游览器会话(Session)时间段内。这通常限于游览器应用程序被关闭之前。
另外,一旦 `Cookie` 从服务器端发送至客户端,服务器端就不存在可以显示删除 `Cookie` 的方法。但可以通过覆盖已过期的 `Cookie` ,实现对客户端 `Cookie` 的实质性删除操作。
* **path 属性**
`Cookie` 的 `path` 属性可用于限制指定 `Cookie` 的发送范围的文件目录。不过另有办法避开这项限制,看来对其作为安全机制的效果不能报有期待。
* **domain 属性**
通过 `Cookie` 的 `domain` 属性指定的域名可做到与结尾匹配一致。比如,当指定 `example.com` 后,除 `example.com` 以外,`www.example.com` 或 `www2.example.com` 等都可以发送 `Cookie` 。
因此,除了针对具体指定的多个域发送 `Cookie` 之外,不指定 `domain` 属性显得更安全。
* **secure 属性**
`Cookie` 的 `secure` 属性用于限制 web 页面仅在 HTTPS 安全连接时,才可以发送 `Cookie` 。
发送 `Cookie` 时,指定 `secure` 属性的方法如下所示。
```http
Set-Cokkie: name=VALUE; secure
```
以上例子仅当在 `https://www........`(HTTPS)安全连接的情况下才会进行 `Cookie` 的回收,也就是说,即使域名相同,`http://www......`(HTTP)也不会发生 `Cookie` 的回收行为。
当省略 `secure` 属性时,不论 HTTP 还是 HTTPS ,都会对 `Cookie` 进行回收。
* **HttpOnly 属性**
`Cookie` 的 `HttpOnly` 属性是 `Cookie` 的扩展功能,它使 JavaScript 脚本无法获得 `Cookie` 。其主要目的为防止跨站脚本攻击(Cross-sitescripting,XSS)对 `Cookie` 的信息窃取。
发送指定 `HttpOnly` 属性的 `Cookie` 的方法如下所示。
```http
Set-Cookie: name=value; HttpOnly
```
通过上述设置,通常从 web 页面内还可以对 `Cookie` 进行读取操作。但使用 JavaScript 的 document.cookie 就无法读取附加 `HttpOnly` 属性后的 `Cookie` 的内容了。因此,也就无法在 XSS 中利用 JavaScript 劫持 `Cookie` 了。
虽然是独立的扩展功能,但 Internet Explorer 6 SP1 以上版本等当下的主流游览器都已经支持该扩展了。另外顺带一提,该扩展并非是为了防止 XSS 而开发的。
### 第二小节 Cookie 字段
```http
Cookie: status=enable
```
首部字段 `Cookie` 会告知服务器,当客户端想获得 HTTP 状态管理支持时,就会在请求中包含从服务器接受到的 `Cookie` 。接受到多个 `Cookie` 时,同样可以以多个 `Cookie` 形式发送。
## 第二节 其他首部字段
HTTP 首部字段是可以自行扩展的。所以在 Web 服务器和游览器的应用上,会出现各种非标准的首部字段。
下面是一些比较常用的首部字段/
* X-Frame-Options
* X-XSS-Protection
* DNT
* P3P
### 第一小节 X-Frame-Options 字段
```http
X-Frame-Options: DENY
```
首部字段 `X-Frame-Options` 属于 HTTP 响应首部,用于控制网站内容在其他 web 网站的 Frame 标签内显示问题。其主要目的是为了防止点击劫持(clickjacking)攻击。
首部字段 `X-Frame-Options` 有以下两个可指定的字段值。
* **DENY**
拒绝
* **SAMEORIGIN**
仅同源域名下的页面(Top-level-browsing-context)匹配时许可。
支持该首部字段的游览器有:Internet Explorer 8、Firefox 3.6.9+、Chrome 4.1.249.1042+、Safari 4+ 和 Opera 10.50+ 等。现在主流的游览器都已经支持。
能在所有的 web 服务端预先设定好 `X-Frame-Options` 字段值是最理想的状态。
当然版本不支持的以及其不放心时可以参考[这篇文章](https://www.cnblogs.com/bella-lin/p/9266994.html)
### 第二小节 X-XSS-Protection 字段
```http
X-XSS-Protection: 1
```
首部字段 `X-XSS-Protection` 属于 HTTP 响应首部,它是针对跨站脚本攻击(XSS)的一种对策,用于控制游览器 `XSS` 防护机制的开关。
首部字段 `X-XSS-Protection` 可指定的字段值如下:
* 0:将 `XSS` 过滤设置成无效状态
* 1:将 `XSS` 过滤设置成有效状态
### 第三小节 DNT 字段
```http
DNT: 1
```
首部字段 `DNT` 属于HTTP 请求首部,其中 `DNT` 是 `Do Not Track` 的简称,意为拒绝个人信息被手机,是表示拒绝被精准广告追踪的一种方法。
首部字段 `DNT` 可指定的字段值如下。
* 0:同意被追踪
* 1:拒绝被追踪
由于首部字段 `DNT` 的功能具备有效性,所以 web 服务器需要对 `DNT` 做出对应的支持。
### 第四小节 P3P字段
```http
P3P: CP="CAO DSP LAW CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa OUR BUS IND UNI COM NAV INT"
```
首部字段 `P3P` 属于HTTP响应首部,通过利用P3P ( The Platform
for Privacy Preferences,在线隐私偏好平台)技术,可以让Web网站上
的个人隐私变成种仅供程序可理解的形式, 以达到保护用户隐私的
目的。
要进行 `P3P`的设定,需按以下步骤进行。
* 步骤一:创建 `P3P` 隐私
* 步骤二:创建 `P3P` 隐私对照文件后,保存命名在 `/w3c/p3p.xml`
* 步骤三:从 `P3P` 隐私中新建 `Compact policies` 后,输出到 HTTP 响应中
关于 `P3P` 的详细规范请查看下面链接。
https://www.w3.org/TR/P3P/
> 作者:肖鹏-SpiritLing 时间:2019-01-30
';
第十节 Last-Modified 字段
最后更新于:2022-04-02 04:41:23
# Last-Modified
> 作者:肖鹏-SpiritLing 时间:2019-11-23
```http
Last-Modified: wed, 25 May 2018 09:11:40 GMT
```
首部字段 `Last-Modified` 指明资源最终修改时间。一般来说,这个值就是 `Request-URI` 指定资源被修改的时间。但类似使用 CGI 脚本进行动态数据处理时,该值有可能会变成数据最终修改时的时间。
> 作者:肖鹏-SpiritLing 时间:2019-11-23
';
第九节 Expires 字段
最后更新于:2022-04-02 04:41:20
# Expires
> 作者:肖鹏-SpiritLing 时间:2019-11-23
```http
Expires: Wed, 04 Jul 2012 08:26:05 GMT
```
首部字段 `Expires` 会将资源失效日期告知客户端。缓存服务器在接收到含有首部字段 `Expires` 的响应后,会以缓存来应答请求,在 `Expires` 字段值指定的时间之前,响应的副本会一直被保存。当超过指定的时间后,缓存服务器在请求发送过来时,会转向源服务器请求资源。
源服务器不希望缓存服务器对资源缓存时,最好在 `Expires` 字段内写入与首部字段 Date 相同的时间值。
但是,当首部字段 `Cache-Control` 有指定 `max-age` 指令时,比起首部字段 `Expires` ,会优先处理 `max-age` 指令。
> 作者:肖鹏-SpiritLing 时间:2019-11-23
';
第八节 Content-Type 字段
最后更新于:2022-04-02 04:41:18
# Content-Type
> 作者:肖鹏-SpiritLing 时间:2019-11-23
```http
Content-Type: text/html; charset=utf-8
```
首部字段 `Content-Type` 说明实体主体内对象的媒体类型。和首部字段 `Accept` 一样,字段值用 `type/subtype` 形式赋值。
> 作者:肖鹏-SpiritLing 时间:2019-11-23
';
第七节 Content-Range 字段
最后更新于:2022-04-02 04:41:16
# Content-Range
> 作者:肖鹏-SpiritLing 时间:2019-11-23
```http
Content-Range: bytes 5001-10000/10000
```
针对范围请求,返回响应时使用的首部字段 `Content-Range` ,能告知客户端作为响应返回的实体哪个部分符合范围请求。字段值以字节为单位,表示当前发送部分及整个实体大小。
> 作者:肖鹏-SpiritLing 时间:2019-11-23
';
第六节 Content-MD5 字段
最后更新于:2022-04-02 04:41:14
# Content-MD5
> 作者:肖鹏-SpiritLing 时间:2019-11-23
```http
Content-MD5: ZTEwYWRjMzk0OWJhNTlhYmJlNTZlMDU3ZjIwZjg4M2U=
```
首部字段 `Content-MD5` 是一串由MD5算法生成的值,其目的在于检查报文主体在传输过程中是否保持完整,以及确认传输到达。
对报文主体执行 MD5 算法获得218位二进制数,再通过 Base64 编码后将结果写入 `Content-MD5` 字段值。由于 HTTP 首部无法记录二进制值,所以要通过 Base64 编码处理。为确保报文有效性,作为接受方的客户端会对报文主体在执行一次相同的MD5算法。计算出的值与字段值作比较候鸟,即可判断出报文主体的准确性。
采用这种方法,对内容上的偶发生性改变是无从查证的,也无法检测出恶意篡改。其中一个原因在于,内容如果能够被篡改,那么同时意味着 `Content-MD5` 也可重新计算然后被篡改。所以处在接受阶段的客户端是无法意识到报文主体以及首部字段 `Content-MD5` 是已经被篡改过的。
> 作者:肖鹏-SpiritLing 时间:2019-11-23
';
第五节 Content-Location 字段
最后更新于:2022-04-02 04:41:11
# Content-Location
> 作者:肖鹏-SpiritLing 时间:2019-11-23
```http
Content-Location: httpo://www.example.com/index.html
```
首部字段 `Content-Location` 给出与报文主题部分相对应的URI。和首部字段 `Location` 不同, `Content-Location` 表示的是报文主体返回资源对应的 URI。
比如,对于使用首部字段 `Accept-Language` 的服务器驱动型请求,当返回的页面内容与实际请求的对象不同时,首部字段 `Content-Location` 内会写明 URI。(访问 http://www.example.com/ 返回的对象却是 http://www.example.com/index.html 等类似情况)。
> 作者:肖鹏-SpiritLing 时间:2019-11-23
';
第四节 Content-Length 字段
最后更新于:2022-04-02 04:41:09
# Content-Length
> 作者:肖鹏-SpiritLing 时间:2019-11-23
```http
Content-Length: 15000
```
首部字段 `Content-Length` 表明了实体主体部分的大小(单位是字节)。对实体主体进行内容编码传输时,不能再使用 `Content-Length` 首部字段。由于实体主体大小的计算方式略微有些复杂,所以在此不再展开。若想一探究竟,可参考 RFC2616 的 4.4 。
> 作者:肖鹏-SpiritLing 时间:2019-11-23
';
第三节 Content-Language 字段
最后更新于:2022-04-02 04:41:07
# Content-Language
> 作者:肖鹏-SpiritLing 时间:2019-11-23
```http
Content-Language: zh-CN
```
首部字段 `Content-Language` 会告知客户端,实体主体使用的自然语言(指中文或英文等语言)。
> 作者:肖鹏-SpiritLing 时间:2019-11-23
';
第二节 Content-Encoding字段
最后更新于:2022-04-02 04:41:05
# Content-Encoding
> 作者:肖鹏-SpiritLing 时间:2019-11-23
```http
Content-Encoding: gzip
```
首部字段 `Content-Encoding` 会告知客户端服务器对实体的主体部分选用的内容编码方式。内容编码是指在不丢失实体信息的前提下所进行的压缩。
主要采用以下4种方式:
* gzip
* compress
* deflate
* identity
> 作者:肖鹏-SpiritLing 时间:2019-11-23
';
第一节 Allow 字段
最后更新于:2022-04-02 04:41:02
# Allow
> 作者:肖鹏-SpiritLing 时间:2019-11-23
```http
Allow : GET,HEAD
```
首部字段 `Allow` 用于通知客户端能够支持 `Request-URI` 指定资源的所有 HTTP 方法。 当服务器接收到不支持的 HTTP 方法时,会以状态码 `405 Method Not Allowed` 作为响应返回。与此同时,还会把所有能支持的 HTTP 方法写入首部字段 `Allow` 后返回。
> 作者:肖鹏-SpiritLing 时间:2019-11-23
';
第六章 HTTP实体首部字段
最后更新于:2022-04-02 04:41:00
# 第六章 HTTP实体首部字段
> 作者:肖鹏-SpiritLing 时间:2019-01-25
## 6.1 响应首部字段列表
| 首部字段名 | 说明 |
| ---|--- |
| [Allow](allow.md) | 服务器支持的HTTP请求方法 |
| [Content-Encoding](content-encoding.md) | 编码方式 |
| [Content-Language](content-language.md) | 实体主体使用的自然语言 |
| [Content-Length](content-length.md) | 实体部分大小 |
| [Content-Location](content-location.md) | 返回资源的URI |
| [Content-MD5](content-md5.md) | 主体执行md5算法 |
| [Content-Range](content-range.md) | 范围请求 |
| [Content-Type](content-type.md) | 媒体类型 |
| [Expires](expires.md) | 资源到期时间 |
| [Last-Modified](last-modified.md) | 最终修改时间 |
## 6.2 响应首部字段
实体首部字段是包含在请求报文和响应报文中的实体部分所使用的首部,用于补充内容的更新时间等与实体时间相关的信息。
> 作者:肖鹏-SpiritLing 时间:2019-01-25
';
第九节 WWW-Authenticate 字段
最后更新于:2022-04-02 04:40:58
# 5.9 WWW-Authenticate
> 作者:肖鹏-SpiritLing 时间:2019-01-20
```http
WWW-Authenticate: Basic realm="Usagidesign Auth"
```
首部字段 `WWW-Authenticate` 用于 HTTP 访问认证。它会告知客户端适用于访问请求 URI 所指定资源的认证方案( `Basic` 或是 `Digest` )和带参数提示的质询(challenge)。状态码 `401 Unauthorized` 响应中,肯定带有首部字段 `WWW-Authenticate` 。
上述示例中,`realm` 字段的字符串是为了辨别请求 URI 指定资源所受到的保护策略。有关该首部,参考本节之后的内容。
> 作者:肖鹏-SpiritLing 时间:2019-01-20
';
第八节 Vary 字段
最后更新于:2022-04-02 04:40:56
# 5.8 Vary
> 作者:肖鹏-SpiritLing 时间:2019-01-15
```http
Vary: Accept-Language
```
首部字段 `Vary` 可对缓存进行控制。源服务器会向代理服务器传达关于本地缓存使用方法的指令。
从代理服务器接受到源服务器返回包含 `Vary` 指定项的响应之后,若再要进行缓存,仅对请求中含有相同 `Vary` 指定首部字段的请求返回缓存。即使对相同资源发起请求,但由于 `Vary` 指定的首部字段不相同,因此必须要从源服务器重新获取资源。
> 作者:肖鹏-SpiritLing 时间:2019-01-15
';
第七节 Server 字段
最后更新于:2022-04-02 04:40:53
# 5.7 Server
> 作者:肖鹏-SpiritLing 时间:2019-01-15
```http
Server : Apache/2.2.17 (Unix)
```
首部字段 `Server` 告知客户端当前服务器上安装的 HTTP 服务器应用程序的信息。不单单会标出服务器上的软件应用名称,还有可能包含版本号和安装时启用的可选项。
```http
Server: Apache/2.26 (Unix) PHP/5.2.5
```
> **注意一点,一旦自己服务器使用的为旧版本,并且漏洞已经被放出来的,最好在隐藏此字段或者自己随意改个名称,以防有人使用已知漏洞攻击服务器**
> 作者:肖鹏-SpiritLing 时间:2019-01-15
';
第六节 Retry-After 字段
最后更新于:2022-04-02 04:40:51
# 5.6 Retry-After
> 作者:肖鹏-SpiritLing 时间:2019-01-15
```http
Retry-After : 120
```
首部字段 `Retry-After` 告知客户端应该在多久之后再次发送请求。主要配合状态码 `503 Service Unavailable` 响应,或 `3xx Redirect` 响应一起使用。
字段值可以指定为具体时间(Wed, 04 Jul 2012 06: 34: 23 GMT 等格式),也可以是创建响应后的秒数。
> 作者:肖鹏-SpiritLing 时间:2019-01-15
';
第五节 Proxy-Authenticate 字段
最后更新于:2022-04-02 04:40:49
# 5.5 Proxy-Authenticate
> 作者:肖鹏-SpiritLing 时间:2019-01-15
```http
Proxy-Authenticate: Basic realm="Usagidesign Auth"
```
首部字段 `Proxy-Authenticate` 会把由代理服务器所要求的认证信息发送给客户端。
它与客户端和服务器之间的 HTTP 访问认证的行为相似,不同之处在于其认证行为是在客户端与代理之间进行的。而客户端与服务器之间进行认证时,首部字段 `WWW-Authorization` 有着相同的作用。有关 HTTP 访问认证,后面会详尽说明。
> 作者:肖鹏-SpiritLing 时间:2019-01-15
';
第四节 Location 字段
最后更新于:2022-04-02 04:40:47
# 5.4 Localtion
> 作者:肖鹏-SpiritLing 时间:2019-01-15
```http
Location: http://www.example.com
```
~~~[sequence]
客户端-->服务器1: GET / www.example.org
服务器1-->客户端: 302 Found \n Location : http://www.example.com
客户端->服务器2: GET / www.example.com
服务器2->客户端: 200 OK
~~~
使用首部字段 `Location` 可以将响应接受方引导至某个与请求 URI 位置不同的资源。
基本上,该字段会配合 `3xx : Redirection` 的响应,提供重定向的 URI。
几乎所有的游览器在接受到包含首部字段 `Location` 的响应后,都会强制性地尝试对已提示的重定向资源的访问。
> 作者:肖鹏-SpiritLing 时间:2019-01-15
';
第三节 ETge 字段
最后更新于:2022-04-02 04:40:45
# 5.3 ETge
> 作者:肖鹏-SpiritLing 时间:2018-11-29
```http
ETge: "fa082-57b5144e55180"
```
首部字段 `ETge` 能够告知客户端实体标识。它是一种可将资源以字符串形式做唯一标识的方式。服务器会为每份资源分配对于的 `ETge` 值时,
另外,当资源更新时,`ETge` 值也需要更新。生成 `ETge` 值时,并没有统一的算法规则,而是仅仅由服务器来分配。
资源被缓存时,就会被分配唯一性标识。例如,当使用中文版的浏览器访问 http://www.google.com 时,就会返回中文版对于的资源,当时有英文版版时,返回的就是英文版资源,两者的 URI 是相同的,所以仅凭 URI 指定缓存的资源是相当困难的。若在下载过程中出现连续中断/再连接的情况,都会依照 `ETge` 值来指定资源。
### 5.3.1 强ETge值和弱ETge值
1. 强 `ETge` 值
强 `ETge` 值,不论实体发生多少细微的变化都会改变其值。
```http
ETge: "usagi-1234"
```
2. 弱 `ETge` 值
弱 `ETge` 值只用于提示资源是否相同。只有资源发生了根本改变,产生差异时才会改变 `ETge` 值。这时,会在字段值最开始处附加 `W/` 。
```http
ETge: W/"usagi-1234"
```
>作者:肖鹏-SpiritLing 时间:2018-11-29
';
第二节 Age 字段
最后更新于:2022-04-02 04:40:42
# 5.2 Age
> 作者:肖鹏-SpiritLing 时间:2018-11-29
```http
Age: 600
```
首部字段 `Age` 能告知客户端,源服务器在多久前创建了响应。字段值单位为秒。
若创建该响应的服务器是缓存服务器,`Age` 值是指缓存后的响应再次发起认证到认证完成的时间值。代理创建响应时必须加上首部字段 `Age`。
> 作者:肖鹏-SpiritLing 时间:2018-11-29
';