6. HTTP首部

6.1 HTTP报文首部

httpstructure

上图是HTTP请求报文的结构

HTTP请求报文由方法、URI、HTTP版本、HTTP首部字段等组成。

请求报文首部信息实例:

1
2
3
4
5
6
7
8
9
10
11
GET / HTTP/1.1
Host: hackr.jp
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/2010010
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*; q=0
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
If-Modified-Since: Fri, 31 Aug 2007 02:02:20 GMT
If-None-Match: "45bae1-16a-46d776ac"
Cache-Control: max-age=0

HTTP响应报文由HTTP版本、状态码(数字和原因短语)、HTTP首部字段三部分组成。

下面是HTTP响应报文结构:

httpresstructure

响应报文的首部实例:

1
2
3
4
5
HTTP/1.1 304 Not Modified
Date: Thu, 07 Jun 2012 07:21:36 GMT
Server: Apache
Connection: close
Etag: "45bae1-16a-46d776ac"

6.2 HTTP首部字段

6.2.1 HTTP首部字段结构

HTTP首部字段传递重要信息,其结构基本如下:

1
2
3
4
5
	首部字段名: 字段值
例如:
Content-Type: text/html
另外,有些首部字段可以有多个值,如下:
Keep-Alive:timeout=15,max=100

6.2.2 HTTP首部字段类型

HTTP首部字段根据实际用途被分为四种类型:

  • 通用首部字段 请求报文和响应报文都会使用到的首部字段
  • 请求首部字段 从客户端向服务端发送请求报文时使用的首部。补充了请求的附加内容、客户端信息、响应内容相关优先级的信息。
  • 响应首部字段 从服务端向客户端发送响应报文时的首部。补充了响应的附加内容,也会要求客户端附加的内容信息。
  • 实体首部字段 针对请求报文和响应报文的实体部分 使用的首部。补充了资源内容更新时间等与实体内容相关的信息。

通用首部字段

首部字段名 说明
Cache-Control 控制缓存的行为
Connection 逐跳首部、连接的管理
Data 创建报文的日期时间
Pragma 报文指令
Trailer 报文末尾的首部一览
Transfer-Encoding 指定报文主体的传输编码方式
Upgrade 升级为其他 协议
Via 代理服务器的相关信息
Warning 错误通知

请求首部字段

首部字段名 说明
Accept 用户代理可处理的媒体类型
Accept-Charset 优先的字符集
Accept-Encoding 优先的内容编码
Authorization Web信息认证
Expect 期待服务器的特定行为
From 用户的电子邮箱地址
Host 请求资源所在的服务器
If-Match 比较实体标记
If-Modified-Since 比较资源的更新时间
If-None-Match 比较实体标记(与If-Match相反)
If-Range 资源未更新时发送实体Byte的范围请求
If-Unmodifield-Since 比较实体标记(与If-Match相反)
Max-Forwards 最大传输逐跳数
Proxy-Authorization 代理服务器要求客户端的认证信息
Range 实体的字节范围请求
Referer 对请求中URL的原始获取方
TE 传输编码优先级
Use-Agent HTTP客户端程序的信息
Accept-Language 优先的语言(自然语言)

响应首部字段

首部字段名 说明
Accept-Ranges 是否接受字节范围请求
Age 推算资源创建经过时间
ETag 资源的匹配资源
Location 令客户端重定向至指定URI
Proxy-Authenticate 代理服务器对客户端的认证信息
Retry-After 对再次发起请求的时机要求
Server HTTP服务器的安装信息
Vary 代理服务器缓存的管理信息
WWW-Authenticate 服务器对客户端的认证信息

实体首部字段

首部字段名 说明
Allow 资源可支持的HTTP方法
Content-Encoding 实体主体适用的编码方式
Content-Language 实体主体的自然语言
Content-Length 实体主体的大小(字节)
Content-MD5 实体主体的报文摘要
Content-Range 实体主体的位置范围
Content-Type 实体主体的媒体类型
Content-Location 替代对应资源的URI
Expires 实体主体过期的日期时间
Last-Modified 资源的最后修改时间

以上就是最常用的一些 HTTP 首部字段。

其他还有一些非 HTTP/1.1 规范的首部字段也用的比较多,比如 Set-Cookie、Cookie 等等。

此外,HTTP 首部根据将定义成缓存代理和非缓存代理的行为,分成了两种类型——端到端首部(End-to-End Header)和逐跳首部(Hop-by-Hop Header)。

端到端首部类的首部字段会转发给请求/响应的最终接受对象,且必须保存在由缓存生成的响应中,另外规定它必须转发;

逐跳首部只对单次转发有效,会因通过缓存或代理而不再转发。HTTP/1.1 之后的版本中使用逐跳首部需要提供 Connection 首部字段。

下面这些字段都属于逐跳首部字段:

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

所有其余字段皆为端到端首部字段。

下面开始详细介绍各个首部字段。

6.2.3 HTTP/1.1 通用首部字段

Cache-Control

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

Cache-Control 的指令参数是可选的,多个指令之间通过逗号分开。该首部字段在请求和响应时都可以使用。

1
Cache-Control:private, max-age = 0 , no-cache

Cache-Control 可用指令如下:

请求指令

指令 参数 说明
no-cache 强制向源服务器再次验证
no-store 不缓存请求或响应的任何内容
max-age=[秒] 必需 响应的最大 age 值
max-stale(=[秒]) 可省略 接受已过期的响应
min-fresh=[秒] 必需 期望在指定的时间内的响应仍然有效
no-transform 代理不可更改媒体类型
only-if-cached 从缓存获得资源
cache-extension - 新指令标记(token)

响应指令

指令 参数 说明
public 可向任意方提供响应的缓存
private 可省略 仅向特定用户返回响应
no-cache 可省略 缓存前必须确认其有效性
no-store 不缓存请求或响应的任何内容
no-transform 代理不可更改媒体类型
must-revalidate 可缓存但必须再向源服务器进行确认
proxy-revalidate 要求中间缓存服务器对缓存的响应有效性再进行确认
max-age=[秒] 必需 响应的最大 age 值
s-maxage=[秒] 必需 公共缓存服务器响应的最大 age 值
cache-extension - 新指令标记(token)

规定是否缓存的指令:

**public指令 ** 当指定使用public指令时 ,则明确表明其他用户也可以利用缓存

1
Cache-Control: public

当指定使用public指令时,则明确表明其他用户也可以利用缓存。

private指令

1
Cache-Control: private

当指定private指令后响应只以特定的用户作为对象,当该对象向服务器发起请求时,服务器会返回缓存的资源

no-cache指令

1
Cache-Control: no-cache

该指令的目的是为了防止使用过期的缓存资源

如果客户端发送的请求包含no-cache指令,则表示客户端将不会接受过期的缓存过得响应。于是,中间的代理服务器必须把请求转发给原服务器。

如果服务器返回的响应中包含no-cache指令,那么缓存服务器不能对资源进行缓存,源服务器以后也将不在对缓存服务器请求中提出的资源有效性进行确认,且进制其对资源响应进行缓存操作。

控制可执行缓存对象的指令

no-store指令

1
Cache-Control: no-store

当使用no-store指令时,按时请求或响应中包含机密信息。

因此该指令规定缓存不能在本地存储请求或响应的任一部分。

s-maxage 指令

1
Cache-Control: s-maxage=604800(单位:秒)

该指令功能和max-age相同,不同点是s-maxage指令只适合于供多位用户使用的公共缓存服务器。当使用smax-age 指令之后,直接会忽略 Expires 字段及 max-age 指令的处理。

max-age 指令

1
Cache-Control: max-age=604800(单位:秒)

当客户端发送的请求中包含 max-age 指令时,如果判定缓存资源的缓存时间数值比指定的数值更小,那么客户端就接收缓存的资源。另外,当指定 max-age 值为 0,那么缓存服务器通常需要将请求转发给源服务器(相当于是 no-cache)。

当服务器返回的响应中包含 max-age 指令时,缓存服务器将不对资源的有效性再做确认,而 max-age 数值代表的是资源保存为缓存的最长时间。

应用 HTTP/1.1 版本的缓存的服务器遇到同时存在 Expires 首部字段的情况时,会优先处理 max-age 指令,而忽略掉 Expires 首部字段。而应用 HTTP/1.0 版本的服务器则恰恰相反。

min-fresh 指令

1
Cache-Control: min-fresh=60(单位:秒)

min-fresh 指令要求缓存服务器返回至少还未过指定时间的缓存资源(即指定时间过后仍然是未过期的资源)。

max-stale 指令

1
Cache-Control: max-stale=3600(单位:秒) 

使用 max-stale 表示接受过期的缓存资源,后面的值表示具体过期的时长,表示响应不能已经过时超过该给定的时间。如果不传递数值,则表示无论经过多久,客户端都能够接受。

only-if-cached 指令

1
Cache-Control: only-if-cached

使用该指令表示客户端仅在缓存服务器本地缓存目标资源的情况下才会要求其返回。即只接受已缓存的资源,并且不用向源服务器检查资源的有效性。若代理服务器本地缓存无响应,则返回 504 Gateway Timeout。

must-revalidate 指令

1
Cache-Control: must-revalidate

使用该指令,代理会向源服务器再次验证即将返回的响应缓存目前是否仍然有效。

使用 must-revalidate 指令会忽略 max-stale 指令。

proxy-revalidate 指令

1
Cache-Control: proxy-revalidate

该指令要求所有的缓存服务器在接收到客户端带有该指令的请求返回响应之前,必须再验证资源的有效性。

no-transform 指令

1
Cache-Control: no-transform

该指令规定无论在请求还是响应中缓存都不能改变实体的媒体类型。

这样可以防止缓存或者代理压缩图片等类似操作。

Connection

这个首部字段有一下两个作用:

  • 控制不再转发给代理的首部自担
  • 管理持久连接
1
Connection: 不再转发的首部字段名

这条语句就表示指定的首部字段不再转发到下一级服务器(可能是代理)。

httpconn

除了上面的功能以外,该首部还可以管理持久连接:

1
Connection: close

该指令明确指定断开当前连接。(HTTP/1.1 的所有连接默认都是长连接)

1
Connection: keep-alive

以上指令明确指定当前连接为长连接。(适用于 HTTP/1.1 版本之前)

Date

该字段表明 HTTP 报文创建的日期和时间。

1
Date: Tue, 03 Jul 2012 04:40:59 GMT

Pragma

该字段是 HTTP/1.1 版本的遗留字段,为了向后兼容而定义。

1
Pragma: no-cache

1
Cache-Control: no-cache

功能一致。

Trailer

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

Transfer-Encoding

该首部字段指定了在传输报文主体时所使用的编码方式。

1
Transfer-Encoding: chunked

Upgrade

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

Via

该首部字段是为了追踪客户端与服务器之间的请求和响应报文的传输路径。

报文经过代理或者网关时,会在首部字段 Via 中附加该服务器的信息,然后再进行转发。而且这个字段不仅可以用于追踪报文的转发,还可以避免请求回环发生。

httpvia

各个代理服务器会向 Via 添加自身服务器的信息。

其中 1.0 以及 1.1 的开头表示服务器的 HTTP 协议版本。

Warning

该首部自担通常告诉用户一些缓存相关的问题的警告,具体格式如下:

1
Warning: [警告码][警告的主机:端口号]“[警告内容]”([日期时间])

6.2.4 HTTP/1.1 请求首部字段

请求首部字段是从客户端发往服务器端时请求报文中所使用的字段。

Accept

1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

该首部字段可以通知服务器,用户代理能够处理的媒体类型及媒体类型的相对优先级。可以使用 type/subtype 的形式一次指定多种媒体类型。

常用媒体类型:

  • 文本文件:

    1
    text/html,text/plain,text/css,application/xhtml+xml,application/xml...
  • 图片文件

    1
    image/jpg,image/gif,image/png...
  • 视频文件

    1
    video/mpeg,video/quicktime...
  • 应用程序使用的二进制文件

    1
    application/octet-stream,application/zip...

多个协议之间使用逗号分隔,分号之前代表媒体类型,分号之后代表权重。

当服务器提供多种内容时,会首先返回权重最高的媒体类型。

Accept-Charset

1
Accept-Charset: iso-8859-5,unicode-1-1;q=0.8

该字段可用来通知服务器用户代理支持的字符集以及字符集的权重。

Accept-Encoding

1
Accept-Encoding: gzip,deflate

该字段用来告知服务器用户代理支持的内容编码及内容编码格式的优先级。

以下是最常用的几个内容编码格式:

  • gzip

    由文件压缩程序gzip(GNU zip)生成的编码 格式(RFC1952)

  • compress

    由UNIX文件压缩程序compress生成的编码格式

  • deflate

    组和使用zlib格式及有deflate压缩算法生成的编码格式

  • identity

    不执行压缩或者不会变化的默认编码格式

Accept-Language

告知服务器能够处理的自然语言

1
Accept-Language: zh-cn,zh;q = 0.7, en-us,en; q = 0.3

Authorization

该字段用于告知服务器用户代理的认证信息。

1
Authorization: Basic dWVub3NlbjpwYXNzd29yZA==

Expect

1
Expect: 100-continue

From

1
From: info@hackr.jp

该字段用来告知服务器使用用户代理的用户电子邮箱地址

Host

很多时候一台服务器上部署了多个网站,对应着多个域名,当 DNS 解析到服务器之后,我们需要知道用户访问的是哪个网址,以便分配到对应的端口给对应的程序进行处理,所以 Host 就用来告知服务器端用户访问的主机名称和端口号。

Host 首部是唯一一个必须被包含在请求内的首部字段。

如果服务器未设定主机名,那么发送一个空值即可

If-Match

形如 If-xxx 的请求首部字段,都可以称为条件请求。服务器接收到条件请求之后,只有在判断条件为真时才会执行请求。

1
If-Match: "123456"

该首部字段属于附带条件之一,它会告知服务器匹配资源所用的实体标记(ETag,后面会讲)值。服务器会比对 If-Match 的字段值和资源的 ETag 值,仅当两者一致时才会执行请求。反之会返回状态码 412 Precondition Failed 的响应。

使用 * 时,服务器会匹配任意的 ETag 值。

If-Modified-Since

该首部字段指定一个时间点,如果在该时间点之后有修改过资源,则会响应请求

1
If-Modified-Since: Thu, 15 Apr 2004 00:00:00 GMT 

如果在这个时间点之后没有修改过资源,则返回304 Not Modified状态码的响应

If-None-Match

该字段与If-Match的作用相反。当该字段的值不匹配资源的ETag时才会响应请求。

If-Range

该字段的值若是跟 ETag 的值或更新的日期时间相匹配,那么就作为范围请求处理;如果无法匹配的话就返回全体资源。

If-Unmodified-Since

1
If-Unmodified-Since: Thu, 03 Jul 2012 00:00:00 GMT

该首部字段和 If-Modified-Since 作用相反,它的作用是告知服务器指定的资源只有在指定日期之后没有发生变更的情况下才处理请求,否则就返回 412 Precondition Failed 状态码。

Max-Forward

通过 TRACE 方法或者 OPTIONS 方法发送包含首部字段 Max-Forward 的请求时,该字段以十进制整数形式指定可经过的服务器的最大数目。

1
Max-Forward: 10

Proxy-Authorization

1
Proxy-Authorization: Basic dGlwObjkNLAGFfY5

该字段告知服务器认证所需要的的信息。该认证行为发生在客户端与代理服务器之间。

Range

1
Range: bytes = 5001-10000

该字段适用于只获取部分资源的范围请求,他告知了服务器所需要的服务器资源的指定范围。

接收到携带该字段请求的服务器返回状态码为206 Partil Content的响应,如果无法处理该范围请求,则服务器会返回状态码为220 OK的响应以及全部资源。

Referer

1
Referer: http://www.hackr.jp/index.htm

该首部字段告知服务器请求的原始资料的URI

TE

1
TE: gzip,deflate;q=0.5

该字段会告知服务器客户端能够处理的响应传世编码方式及相对的优先级,其功能和Transfer-Enconding的功能相似。

User-Agent

1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0.1

该字段会将创建请求的浏览器和用户代理名称的相关信息发送给服务器。当爬虫发起请求时,有可能会在该字段添加作者的地址。

值得一提的是有些网站会做出反爬虫策略,他们会验证 User-Agent 字段是否来自于浏览器,如果不是的话就会拒绝爬虫的请求;所以如果要想继续拿到想要的信息的话就会通过该字段将爬虫伪造成浏览器。

6.2.4 HTTP/1.1 响应首部字段

响应首部字段是由服务器端向客户端返回响应报文中所使用的字段,用于补充响应的附加信息、服务器信息,以及对客户端的附加要求信息等。

Accept-Ranges

1
Accept-Ranges: bytes

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

Age

1
Aag: 600

该首部字段告知客户端源服务器在多久之前创建了响应,字段的值的单位为秒。

若创建该响应的服务器是缓存服务器,Age 值是指缓存后的响应再次发起认证到再次认证完成的时间值。

ETag

1
ETag: "82e22293907ce725faf67773957acd12"

首部字段 ETag 能告知客户端实体标志。它是一种能够将资源以字符串形式做唯一性标志的方式。服务器会为每份资源分配对应的 ETag 值。

当资源更新时,ETag 值也要更新。完成 ETag 值时,并没有统一的算法规则,仅仅由服务器分配。

访问某个资源的 URI 一般不会发生改变,但是当资源本身发生了变化时,资源对应的 ETag 也会更新。

强 ETag 和弱 ETag

ETag 值有强弱之分,强 ETag 值不管资源发生多么细微的变化都会随之变化,而弱 ETag 值只有在资源发生了根本改变并产生差异时才会发生变化。

Location

1
Location: http://www.usagidesign.jp/sample.html

该首部字段可以将接受响应的客户端引导到某一个与其请求 URI 位置不同的资源。

基本上该字段会配合 3xx 重定向状态码一起使用。

Proxy-Authenticate

1
Proxy-Authenticate: Basic realm="Usagidesign Auth"

该首部字段会把代理服务器所要求的认证信息发送给客户端。

Retry After

1
Retry-After:120

该首部字段告知客户端在多久之后再次发起请求。该字段可以指定为具体的时间或者创建响应后的秒数。

Server

该首部字段会告知客户端当前服务器上安装的 HTTP 服务器应用程序的信息。

1
Server: Apache/2.2.17 (Unix)

Vary

1
Vary: Accept-Language

该首部字段可对缓存进行控制,源服务器会向代理服务器传达关于本地缓存使用方法的命令。

具体来说,该首部字段会指定一个其他的首部字段,比如上面的 Accept-Encoding,当指定字段的值未发生变化时,则使用缓存资源;如果指定字段的值发生了变化时,则需要向源服务器请求最新的资源。

这个字段可以指定 User-Agent,防止移动端浏览器访问页面时访问了 PC 端页面的缓存。

当该字段指定为 * 时,所有的请求都会被视为唯一的并且会被缓存。

WWW-Authenticate

1
WWW-Authenticate: Basic realm="Usagidesign Auth"

该首部字段用于 HTTP 访问认证。

6.2.4 HTTP/1.1 实体首部字段

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

Allow

1
Allow:GET,HEAD

该首部字段用于通知客户端服务器能够支持的 HTTP 方法,当服务器接收到不支持的请求方法时,会返回 405 Not Allowed 状态码。

Content-Encoding

1
Content-Encoding:gzip

该首部字段会告知客户端对实体的主体部分所使用的内容编码格式。

具体编码格式可以参考 2.5.3 Accept-Encoding。

Content-Language

1
Content-Language; zh-CN

该首部字段用于通知客户端实体主体所使用的自然语言。

Content-Length

1
Content-Length:15000

该首部字段表明了实体主体的大小(单位是字节)。

如果对实体主体采用了内容编码传输时,不能再使用 Content-Length 首部字段。

Content-Location

1
Content-Location:http://www.hackr.jp/index-ja.html

该首部字段给出与报文主体相对应的 URI。当返回的页面内容与请求的实际对象不相同时,首部字段 Content-Location 会写明 URI。

Content-MD5

1
Content-MD5: OGFkZDUwNGVhNGY3N2MxMDIwZmQ4NTBmY2IyTY==

客户端会对接收到的报文主体采用 MD5 算法进行散列计算,然后与 Content-MD5 的值进行比较以对接收到的主体内容进行完整性校验。

散列算法进行计算的做法主要用于防止传输内容被篡改,因为同一个输入通过散列算法计算以后得到的结果是相同的,不同的输入经过散列算法计算之后得到的结果基本不会重复。这也是许多提供资源下载的网站同时会给出资源对应 HASH 值的原因。

但是 Content-MD5 并不可靠,因为如果传输主体的内容可以被修改的话,Content-MD5 的值同样也可能被修改过,所以并不可靠。为了确保资源不被篡改,最好还是使用 HTTPS。

Content-Range

1
Content-Range: bytes 5001-10000/10000

针对范围请求,该首部字段告知客户端返回的响应的实体的哪些部分符合范围请求,单位为字节。

Content-Type

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

该首部字段说明了实体主体内的媒体类型。

Expires

1
Expires: Wed, 04 Jul 2012 08:26:05 GMT

该首部字段将资源失效的日期告知客户端。

当首部字段 Cache-Control 有指定 max-age 指令时,会优先处理 max-age 指令。

Last-Modified

1
Last-Modified: Wed, 23 May 2012 09:59:55 GMT

该首部字段指明了资源的最终修改时间。

Cookie 的工作机制是用户识别及状态管理

为 cookie 服务的首部字段:

首部字段名 说明 首部类型
Set-Cookie 开始状态管理所使用的 Cookie 信息 响应首部字段
Cookie 服务器接收到的 Cookie 信息 请求首部字段

当服务器开始准备管理客户端的状态时,会实现告知各种信息。

下面的表格列举了 Set-Cookie 的字段值。

属性 说明
NAME=VALUE 赋予 Cookie 的键和对应值
expires=DATE Cookie 的有效期
path=PATH 将服务器上的文件目录作为 Cookie 的适用对象(若不指定则默认为文档所在的文件目录)
domain=域名 作为 Cookie 适用对象的域名(若不指定则默认为创建 Cookie 的服务器的域名)
Secure 仅在 HTTPS 安全通信时才发送 Cookie
HttpOnly 加以限制,使 Cookie 不能被 JavaScript 所访问

下面详细讲讲 Cookie 的各个属性。

  • expires:该属性指定浏览器可以发送 Cookie 的有效期。当省略 expires 属性时,其有效期仅限于维持浏览器会话(Session)时间段内。这通常限于浏览器关闭之前。

    另外需要注意的是一旦 Cookie 从服务器端发送到客户端,服务器端就不存在可以显式删除 Cookie 的方法。只能通过覆盖已有的 Cookie 来达到删除的目的。

  • path:该属性用于限定指定 Cookie 的发送范围的文件目录。但是有其他办法可以避开这个限制,所以不要对它抱有太大期望。

  • domain:该属性的域名可做到与结尾匹配一致,比如指定 domain 为 example.com,此时 www.example.com 和 www2.example.com 也都可以访问 Cookie。所以不指定域名的情况下更加安全,因为默认只有当前响应的服务器的域名可以访问 Cookie。

  • secure:该属性限制 Web 页面仅在 HTTPS 安全连接时才发送 Cookie。当省略该属性时,HTTP 和 HTTPS 协议的指定域名都可以访问 Cookie。

  • HttpOnly:该属性使得 JavaScript 无法对 Cookie 进行读取操作。

1
Cookie:status=enable

首部字段 Cookie 会告知服务器,当客户端想要获得 HTTP 状态管理的支持时,就会在请求中包含从服务器中获取到的 Cookie。

其他首部字段

HTTP 首部字段是可以自行扩展的,所以在 Web 服务器和浏览器的应用上,会出现一些非标准的首部字段。

下面是比较常用的非标准首部字段:

  • X-Frame-Options
  • X-XSS-Protection
  • DNT
  • P3P

X-Frame-Options

1
2
X-Frame-Options: DENY
此处的 Frame 包括 iframe、frame、object 等标签

该首部字段属于 HTTP 响应首部,用于控制网站内容在其他 Web 网站的 Frame 标签内的显示问题。其主要目的是防止点击劫持攻击(clickjacking)。

该字段可以指定三类值:

  • DENY:拒绝被嵌套到 Frame,即使是相同域名下的页面也不行
  • SAMEORIGIN:该页面只可以被嵌入到相同域名页面的 Frame 中
  • ALLOW-FROM uri:表示可以在指定来源的页面中被嵌套

X-XSS-Protection

该字段属于响应首部,是针对跨域脚本攻击的一种策略,用于控制浏览器 XSS 防护机制的开关。

该字段可以设置一下了两个值:

  • 0:将 XSS 过滤设置成无效状态
  • 1:将 XSS 过滤设置成有效状态

DNT

1
DNT:1

该首部字段属于 HTTP 请求首部,其中 DNT 是 Do Not Track 的简称,表示拒绝个人信息被收集。

0 表示同意被追踪,1 表示拒绝被追踪。

P3P

该首部字段属于响应首部,通过利用 P3P 技术让网站上的个人隐私变成仅供程序可理解的形式。

7. HTTPS

7.1 HTTP的缺点

HTTP在通信过程中会面临以下三种安全问题:

  • 通信使用明文(不加密),内容可能会被监听
  • 不验证通信方的身份,可能会遭遇伪装
  • 无法验证报文的完整性,可能已经被篡改

谷歌浏览器强制要求https

7.1.1 窃听

HTTP本身不具备加密功能,所以传输的过程中都是以明文 方式发送

由于在网络的传输过程中,我们所发送的信息要 经过许多的网络节点和设备,在这个过程中这些设备是可能会拦截我们的信息并且进行窃听的,直接通过一些常用的抓包工具就可以窃听未加密的网络传输信息。

通过加密防止窃听

  • 通信的加密 为了防止传输内容被窃听,我们采取的方式之一就是通信加密,HTTP本身没有加密机制,但是我们可以通过将HTTP和SSL(Secure Socket Layer 安全套接层) 或者 TLS(Transport Layer Security 安全传输协议)组和使用来加密传输内容。

    用 SSL 建立安全通信线路以后,就可以在这条线路上进行 HTTP 通信了。与 SSL 组合使用的 HTTP 被称为 HTTPS(HTTP Secure)

  • 内容的加密 还有一种方式就是将参与通信的内容本身进行加密。这样的话就需要客户端对HTTP报文加密后再请求发送。由于该方式不同于HTTPS将整个通信线路加密的方式,所以内容仍然会有被篡改的风险。

7.1.2 伪装

HTTP 协议本身并不会对通信的另一方进行身份验证,所以任何人都能对服务器发起请求。

不验证通信方可能就会存在各种安全隐患:

  • 客户端无法确认自己的请求是否发送到了目标服务器或者返回响应的服务器是否是目标服务器,有可能是伪装了的服务器。
  • 服务器无法确认向自己发起请求的客户端以及自己返回响应的客户端是否是目标中的客户端。
  • 无法确认通信方是否具备访问权限,因为某些服务器只想给特定的用户访问。
  • 即使是无意义的请求也会照单全收,使得服务器可能遭受到 DDoS 攻击。

通过查明对方证书来防止伪装

SSL不仅提供加密处理,而且使用了一种称为证书的手段,可用于确认对方身份。

证书由第三方机构颁发,用以证明服务器的客户端是实际存在的。

httpcert

通过使用证书可以证明通信方就是意料中的服务器。对使用者而言,也减少了个人信息泄露的风险。

另外,客户端持有证书即可完成个人身份的认证,也可用于对网站的认证环节。

7.1.3 篡改

HTTP协议通常无法确认信息的完整性,一旦传输的信息被篡改,那么信息就失去了准去性,导致信息有误。比如你想在某一个网站的下载一个资源,而你的资源传输已经被被人劫持,在你发起下载请求的时候,你所接收到的资源正在被人修改,所以你下载到的资源就不是你想要的那个了。

像这样,请求或者响应在传输途中遭攻击者拦截并篡改内容的攻击称为中间人攻击(Man-in-the-Middle attack, MitM)。

如何防止篡改

之前的章节有提到过Content-MD5 实体首部字段可用于确认实体内容是否完整,但是由于Content-MD5本身的值也有可能被篡改,所以这个字段并不可靠,所以需要其他方法来确保传输的内容不被篡改。

通过其他散列算法来计算传输内容是否完整也不可靠,那么我们最终还是需要HTTPS来帮我解决这个问题。SSL提供认证和加密处理以及摘要功能

7.2 HTTPS

1
HTTPS = HTTP + 加密 + 认证 + 摘要

7.2.1 HTTPS是身披SSL外壳的HTTP

HTTPS 并非是应用层的一种新协议。只是 HTTP 通信接口部分用 SSL 和 TLS 协议代替而已。

通常,HTTP 直接和 TCP 通信。当使用 SSL 的时候,就先和 SSL 通信,再由 SSL 和 TCP 通信了。所以简而言之,HTTPS 就是身披 SSL 外壳的 HTTP 协议。

https

在采用 SSL 以后,HTTP 就拥有了 HTTPS 的加密、证书和完整性保护功能了。

SSL 协议是独立于 HTTP 的协议,所以其他协议也可以采用 SSL 协议,它是当今世界上应用最广泛的网络安全技术

7.2.2 相互交换秘钥的公开秘钥加密技术

在将SSL之前可以了解一下加密技术,SSL采用一种叫做公开秘钥加密(Public-key Cryptography)的加密处理技术。

近代的加密方法中,加密算法是公开的,但是秘钥是保密的。加密和解密都会用到秘钥。没有秘钥无法对秘钥进行解密。反过来说没任何人只要拿到秘钥就可以解密信息。如果秘钥被攻击者获得,那加密就失去了意义

  • 共享密钥加密的困境

    加密和解密使用同一个密钥的方式称为共享密钥加密(Common key crypto system),也被叫做对称密钥加密

    采用共享密钥加密方式加密时,需要将密钥一起发送给通信方,所以有需要考虑密钥传输的安全性,需要设法安全地保管密钥,这便是共享密钥加密方式的困扰。

  • 使用两把秘钥加密的公开秘钥加密方式

    公开密钥加密方式很好的解决了共享密钥加密方式的困扰。

    公开密钥加密使用一对非对称的密钥。一把叫做私有密钥(private key),另一把叫做公开密钥(public key)。顾名思义,私有密钥不能被其他任何人知道,而公开密钥则可以仁任意传播,任何人都可以拿到。

    使用公开密钥加密方式(非对称加密),发送密文的一方使用公钥进行加密处理,而接收方拿到被加密后的信息之后再使用自己的私钥进行解密。利用这种方式进行传输,就不需要发送密钥,也就不用担心密钥被攻击者拿走了。

  • HTTPS采用混合加密机制

    HTTPS采用共享秘钥加密方式和公开秘钥加密方式混合的加密方式。

    如果秘钥可以被安全传输,则HTTPS会考虑采用共享加密方式,否则将采用公开秘钥加密方式。这是因为公开密钥加密方式的速度比共享密钥加密方式要慢。HTTPS充分地利用了两者的有点,将多种方法组合起来用于通信。在使用公开密钥加密方式交换密钥之后,之后的信息传输使用共享密钥加密方式

7.2.3 证明公开密钥正确性的证书

遗憾的是公开密钥加密方式本身也是有缺陷的,那就是无法证明公开的密钥本身是货真价实的。

为了解决上面说到的问题,可以使用由数字证书认证机构(CA,Certificate Authority)和其相关机构颁发的公开密钥证书。

数字证书认证机构处于客户端与服务端双方都信赖的第三方机构的立场上,威瑞新(VeriSign)就是其中一家非常有名的数字证书认证机构。

下面讲解一下数字证书认证机构的业务流程:

首先,服务器的运营人员会向数字机构提出公开密钥申请,CA 在认证申请者的身份信息之后,会对已申请的公开密钥进行数字签名,然后分配这个已签名的公开密钥,并将该公开密钥放入公钥证书之后绑定在一起。

服务器会将这份 CA 颁发的公钥证书发送给客户端,以进行公钥加密方式通信,公钥证书也可叫做数字证书或者直接称为证书。

接到证书的客户端可使用 CA 的公钥对证书的数字签名进行认证,一旦验证通过,客户端便可确认两件事:

  • 认证服务器公钥的机构是真实有效的 CA 机构
  • 服务器的公钥是值得信任的

于是这就达到了确认公钥真实有效性的目的。

安全地转交 CA 机构的密钥给客户端是一件困难的事,因此多数浏览器会在内部植入常用认证机构的公钥。

httpskey

  • 可证明组织真实性的 EV SSL 证书

    证书的一个作用是证明作为通信一方的服务器是否符合规范,另一个作用是确认服务器运营商企业是否真实存在。能够证明企业真实性的正式就是 EV SSL 证书(Extended Validation SSL Certificate)。

    该证书的目的是为了防止钓鱼攻击(Phishing)。

  • 用以确认客户端的客户端证书

    HTTPS 中还可以使用客户端证书对客户端进行认证。

7.4 HTTPS的安全通信机制

为了更好的理解 HTTPS,我们来观察一下 HTTPS 的通信步骤。

img

  • 步骤1:客户端通过发送 Client Hello 报文开始 SSL 通信。报文中包含客户端支持的 SSL 的指定版本、加密组件(Cipher Suite)列表(所使用的加密算法及密钥长度等)。
  • 步骤2:服务器可进行 SSL 通信时,会以 Server Hello 报文作为应答。和客户端一样,在报文中包含 SSL 版本以及加密组件。服务器的加密组件内容是从接收到的客户端加密组件内筛选出来的。
  • 步骤3:之后服务器发送 Certificate 报文。报文中包含公开密钥证书。
  • 步骤4:最后服务器发送 Server Hello Done 报文通知客户端,最初阶段的 SSL 握手协商部分结束。
  • 步骤5:SSL 第一次握手结束之后,客户端以 Client Key Exchange 报文作为回应。报文中包含通信加密中使用的一种被称为 Pre-master secret 的随机密码串。该报文已用步骤 3 中的公开密钥进行加密。
  • 步骤6:接着客户端继续发送 Change Cipher Spec 报文。该报文会提示服务器,在此报文之后的通信会采用 Pre-master secret密钥加密。
  • 步骤7:客户端发送 Finished 报文。该报文包含连接至今全部报文的整体校验值。这次握手协商是否能够成功,要以服务器是否能够正确解密该报文作为判定标准。
  • 步骤8:服务器同样发送 Change Cipher Spec 报文。
  • 步骤9:服务器同样发送 Finished 报文。
  • 步骤10:服务器和客户端的 Finished 报文交换完毕之后,SSL 连接就算建立完毕。当然,通信会受到 SSL 的保护。从此处开始进行应用层协议的通信,即发送 HTTP 请求。
  • 步骤11:应用协议通信,即发送 HTTP 响应。
  • 步骤12:最后由客户端断开连接。断开连接时,发送 close_notify 报文。

在以上流程中,应用层发送数据时会附加一种叫做 MAC(Message Authentication Code)的报文摘要。MAC 能够查知报文是否遭到篡改,从而保护报文的完整性。

下面是对整个流程的图解。图中说明了从仅适用服务器端的公开密钥证书(服务器证书)建立 HTTPS 通信的整个过程。

image-20201022150748120

SSL 速度慢吗

HTTPS 也存在一些问题,那就是当使用 SSL 时,它的处理速度会变慢。

SSL 的慢是分两种。一种是指通信慢。另一种是指由于大量消耗 CPU 及内存等资源,导致处理速度变慢。

和使用 HTTP 相比,网络负载可能会变慢 2 到 100 倍。除去和 TCP 连接、发送 HTTP 请求/响应外,还必须进行 SSL 通信,因此整体上处理通信量不可避免会增加。

另一点是 SSL 必须进行加密处理。在服务器和客户端都需要进行加密和解密的运算处理。因此从结果上讲,比起 HTTP 会更多地消耗服务器和客户端的硬件资源,导致负载增强。

针对速度变慢这一问题,并没有根本性的解决方案,我们会使用 SSL 加速器这种(专用服务器)硬件来改善该问题。该硬件为 SSL 通信专用硬件,相对软件来讲,能够提高数倍 SSL 的计算速度。仅在 SSL 处理时发挥 SSL 加速器的功效,以分担负载。

为什么不一直使用 HTTPS

  1. 因为与纯文本通信相比,加密通信会消耗更多的 CPU 及内存资源。如果每次通信都加密,会消耗相当多的资源,平摊到一台计算机上时,能够处理的请求数量也必然减少。因此,如果是非敏感信息则使用 HTTP 通信,只有在包含个人信息等敏感数据时,才利用 HTTPS 加密通信。
  2. 除此之外,想要节约购买证书的开销也是原因之一。

8. 确认访问用户身份的认证

8.1 何为认证

计算机本身无法判断坐在显示器前的使用者的身份,为了确认是谁在访问服务器,需要核对“登录者本人才知道的信息”、“登录者本人才会有的信息”。核对的信息通常是指以下这些:

  • 密码:只有本人才会知道的字符串信息。
  • 动态令牌:仅限本人持有的设备内显示的一次性密码。
  • 数字证书:仅限本人(终端)持有的信息。
  • 生物认证:指纹和虹膜等本人的生理信息
  • IC 卡等:仅限本人持有的信息。

HTTP/1.1 使用的认证方式如下所示:

  • BASIC认证(基本认证)
  • DIGEST认证(摘要认证)
  • SSL 客户端认证
  • FormBase 认证(基于表单认证)

8.2 BASIC 认证

BASIC 认证(基本认证)是从 HTTP/1.0 就定义的认证方式。即便是现在仍有一部分的网站会使用这种认证方式。是 Web 服务器与通信客户端之间进行的认证方式。

image-20201022151634964

步骤1:当请求的资源需要 BASIC 认证时,服务器会随状态码 401 Authorization Required,返回带 WWW-Authenticate 首部字段的响应。该字段内包含认证的方式(BASIC)及 Request-URI 安全域字符串(realm)。

步骤2:接收到状态码 401 的客户端为了通过 BASIC 认证,需要将用户 ID 及密码发送给服务器。发送的字符串内容是由用户 ID 和密码构成,两者中间以冒号(:)连接后,再经过 Base64 编码处理。将编码后的字符串写入首部字段 Authorization 后,发送请求。

步骤3:接收到包含首部字段 Authorization 请求的服务器,会对认证信息的正确性进行验证。如验证通过,则返回一条包含 Request-URI 资源的响应。

BASIC 认证虽然采用 Base64 编码方式,但这不是加密处理。不需要任何附加信息即可对其解密。换言之,由于明文解码后就是用户 ID 和密码,在 HTTP 等非加密通信的线路上进行 BASIC 认证的过程中,如果被人窃听,被盗的可能性极高。

另外,除此之外想再进行一次 BASIC 认证时,一般的浏览器却无法实现认证注销操作,这也是问题之一。

BASIC 认证使用上不够灵活,且达不到多数 Web 网站期望的安全性等级,因此它并不常用。

8.3 DIGEST 认证

为弥补 BASIC 认证存在的弱点,从 HTTP/1.1 起就有了 DIGEST 认证。DIGEST 认证同样使用质询/响应的方式(challenge/response),但不会像 BASIC 认证那样直接发送明文密码。

所谓质询响应方式是指,一开始一方会先发送认证要求给另一方,接着使用从另一方那接收到的咨询码计算生成响应码。最后将响应码返回给对方进行认证的方式。

img

因为发送给对方的只是响应摘要及由知讯码产生的计算结果,所以比起 BASIC 认证,密码泄露的可能性就降低了。

  • DIGEST 认证的认证步骤

img

步骤1:请求需认证的资源时,服务器会随着状态码 401 Authorication Required,返回带 WWW-Authenticate 首部字段的响应。该字段内包含质问响应方式认证所需要的临时咨询码(随机数,nonce)。

首部字段 WWW-Authenticate 内必须包含 realm 和 nonce 这两个字段的信息。客户端就是依靠向服务器回送这两个值进行认证的。

nonce 是一种每次随返回的 401 响应生成的任意随机字符串。该字符串通常推荐由 Base64 编码的十六进制数的组成形式,但实际内容依赖服务器的具体实现

步骤2:接收到401 状态码的客户端,返回的响应中包含 DIGEST 认证必须的首部字段 Authorization 信息。首部字段 Authorization 内必须包含 username、realm、nonce、uri 和 response 的字段信息,其中,realm 和 nonce 就是之前从服务器接收到的响应中的字段。

步骤3:接收到包含首部字段 Authorization 请求的服务器,会确认认证信息的正确性。认证通过后则会返回包含 Request-URI 资源的响应。

并且这时会在首部字段 Authorization-Info 写入一些认证成功的相关信息。

8.4 SSL客户端认证

SSL 客户端认证是借由 HTTPS 的客户端证书完成认证的方式。凭借客户端证书认证,服务器可确认访问是否来自登录的客户端。

  • SSL 客户端认证的认证步骤

为达到 SSL 客户端认证的目的,需要事先将客户端证书分发给客户端,且客户端必须安装此证书。

步骤1:接收到需要认证资源的请求,服务器会发送 Certificate Request 报文,要求客户端提供客户端证书。

步骤2:用户选择将发送的客户端证书后,客户端会把客户端证书信息以 Client Certificate 报文方式发送给服务器。

步骤3:服务器验证客户端证书验证通过后方可领取证书内客户端的公开密钥,然后开始 HTTPS 加密通信。

  • SSL 客户端认证采用双因素认证

在多数情况下,SSL 客户端认证不会仅依靠证书完成认证,一般会和基于表单认证组合形成一种双因素认证来使用。所谓双因素认证就是指,认证过程中不仅需要密码这一个因素,还需要申请认证者提供其他持有信息,从而作为另一个因素,与其组合使用的认证方式。

换言之,第一个认证因素的 SSL 客户端证书用来认证客户端计算机,另一个认证因素的密码则用来确定这是用户本人的行为。

  • SSL 客户端认证必要的费用

使用 SSL 客户端认证需要用到客户端证书,而客户端证书需要支付一定费用才能使用。

8.5 基于表单认证

基于表单的认证方法并不是在 HTTP 协议中定义的。客户端会向服务器上的 Web 应用程序发送登录信息,按登录信息的验证结果认证。

多数情况下,输入已事先登录的用户 ID 和密码等登录信息后,发送给 Web 应用程序,基于认证结果来决定认证是否成功。

第八章要讲的内容不多,所以把最重要的一点挪到了这一篇笔记。

关于用户身份的认证,现在多数是采用表单认证,一般会采用 Cookie 来管理 Session(会话)。

大致流程如下:

httpsession

具体步骤如下:

  • 客户端把用户的 ID 密码等登录信息放入报文的实体部分,通常用 POST 方法发送至服务器端。
  • 服务器生成并发放用来识别客户的 Session ID,这个 Session ID 同时会在服务器端保存,然后通过 Set-Cookie 字段绑定到客户端。顺便可以使用 httponly 属性来禁止 JavaScript 修改 Cookie,防止跨站脚本攻击。
  • 客户端把 Session ID 保存在本地 Cookie,下次访问时再带上。服务器端通过验证接收到的 Session ID 来识别用户,从数据库中可以顺便取到与用户相关的一系列信息。

9.基于 HTTP 的功能追加协议

9.1 基于 HTTP 的协议

HTTP 功能上的不足可通过创建一套全新的协议来弥补。可是目前基于 HTTP 的 Web 浏览器的使用环境已遍布全球,因此无法完全抛弃 HTTP。有一些新协议的规则是基于 HTTP 的,并在此基础上添加了新的功能。

9.2 消除 HTTP 瓶颈的 SPDY

Google 在 2010 年发布了 SPDY,其开发目标旨在解决 HTTP 的性能瓶颈,缩短 Web 页面的加载时间(50%)。

9.2.1 HTTP 的瓶颈

HTTP 存在以下缺点和不足:

  • 一条连接上只可发送一个请求
  • 请求只能从客户端开始,客户端不可以接收除响应以外的指令
  • 请求/响应首部未经压缩就发送,首部信息越多延迟越大
  • 发送冗长的首部,每次互相发送相同的首部造成的浪费较多
  • 可任意选择数据压缩格式,非强制压缩发送

image-20201022154013733

  1. Ajax 的解决办法

Ajax 是一种有效利用 JavaScript 和 DOM 的操作,以达到局部 Web 页面替换加载的异步通信手段。和以前的同步通信相比,由于它只更新一部分页面,响应中传输的数据量会因此而减少。

而利用 Ajax 实时地从服务器获取内容,有可能会导致大量请求产生。

image-20201022154032725

  1. Comet 的解决办法
    一旦服务器有内容更新了,Comet 不会让请求等待,而是直接给客户端返回响应。这是一种通过延时应答,模拟实现服务器向客户端推送的功能。

内容上虽然可以做到实时更新,但为了保留响应,一次连接的持续时间也变长了。期间,为了维持连接会消耗更多的资源。

image-20201022154055953

9.2.2 SPDY 的设计与功能

SPDY 没有完全改写 HTTP 协议,而是在 TCP/IP 的应用层与运输层之间通过新加会话层的形式运作。同时,考虑到安全性问题,SPDY 规定通信中使用 SSL。

SPDY 以会话层的形式加入,控制对数据的流动,但还是采用 HTTP 建立通信连接。因此,可照常使用 HTTP 的 GET 和 POST 等方法,Cookie 以及 HTTP 报文等。

image-20201022154125271spdy.png

使用 SPDY 后,HTTP 协议额外获得以下功能。

  • 多路复用流:通过单一的 TCP 连接,可以无限制处理多个 HTTP 请求。所有请求的处理都在一条 TCP 连接上完成,因此 TCP 的处理效率得到提高。
  • 赋予请求优先级:SPDY 不仅可以无限制地并发处理请求,还可以给请求逐个分配优先级顺序。这样主要是为了在发送多个请求时,解决因带宽低而导致响应变慢的问题。
  • 压缩 HTTP 首部:压缩 HTTP 请求和响应的首部。这样一来,通信产生的数据包数量和发送的字节数就更少了
  • 推送功能:支持服务器主动向客户端推送数据的功能。这样,服务器可直接发送数据,而不必等待客户端的请求。
  • 服务器提示功能:服务器可以主动提示客户端请求所需的资源。

9.2.3 SPDY 消除 Web 瓶颈了吗

因为 SPDY 基本上只是将多个域名(IP 地址)的通信多路复用,所以当一个 Web 网站上使用多个域名下的资源,改善效果就会收到限制。

9.3 使用浏览器进行全双工通信的 WebSocket9

WebSocket 是为解决 HTTP 协议所面临的困难的一种新的协议及 API。

9.3.1 WebSocket 的设计与功能

WebSocket,即 Web 浏览器与 Web 服务器之间全双工通信标准。仍在开发中的 WebSocket 技术主要是为了解决 Ajax 和 Comet 里 XMLHttpRequest 附带的缺陷所引起的问题。

9.3.2 WebSocket 协议

一旦 Web 服务器与客户端之间建立起 WebSocket 协议的通信连接,之后所有的通信都依靠这个专用协议进行。通信过程中可相互发送 JSON、XML、HTML 或图片等任意格式的数据。

由于是建立在 HTTP 基础上的协议,因此连接的发起方仍是客户端,而一旦确立 WebSocket 通信连接,不论服务器还是客户端,任意一方都可直接向对方发送报文。

下面我们列举一下 WebSocket 协议的主要特点:

  • 推送功能:支持由服务器向客户端推送数据的推送功能
  • 减少通信量:只要建立起 WebSocket 连接,就希望一直保持连接状态。和 HTTP 相比,不但每次连接时的总开销减少,而且由于 WebSocket 的首部信息很小,通信量也相应较少了。

为了实现 WebSocket 通信,在 HTTP 连接建立之后,需要完成一次 “握手” 的步骤。

  1. 握手·请求
    为了实现 WebSocket 通信,需要用到 HTTP 的 Upgrade 首部字段,告知服务器通信协议发送改变,已达到握手的目的。
1
2
3
4
5
6
7
8
“GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

Sec-WebSocket-Protocol 字段内记录着握手过程中必不可少的键值,Sec-WebSocket-Protocol 字段内记录使用的子协议。

子协议按 WebSocket 协议标准在连接分开使用时,定义那些连接的名称。

  1. 握手·响应
    对于之前的请求,返回状态码 101 Switching Protocols 的响应。
1
2
3
4
5
“HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat”

Sec-WebSocket-Accept 的字段值是由握手请求中的 Sec-WebSocket-Accept 的字段值生成的。

成功握手确立 WebSocket 连接之后,通信时不再使用 HTTP 的数据帧,而采用 WebSocket 独立的数据帧。

image-20201022154245807

9.4 期盼已久的 HTTP/2.0

HTTP/2.0 在 2014 年 11 月实现标准化。

  • HTTP/2.0 的特点
    HTTP/2.0 的目标是改善用户在使用 Web 时的速断体验。

HTTP/2.0 围绕着主要的 7 项技术进行讨论。

压缩 SPDY、Friendly
多路复用 SPDY
TLS 义务化 Speed + Mobility
协商 Speed + Mobility
客户端拉拽 Speed + Mobility
流量控制 SPDY
WebSocket Speed + Mobility

11.常见的Web攻击技术

11.1 跨站脚本攻击

跨站脚本攻击(Cross-Site Scripting , XSS) 是指通过存在安全漏洞的web网站注册用户的浏览器运行非法的HTML标签或者JavaScrip代码的一种攻击方式。动态创建的HTML可能存在安全漏洞。

该攻击可能造成以下影响:

  • 利用虚假输入表单骗取用户个人信息
  • 利用脚本窃取用户的 Cookie 值,被害者在不知情的情况下,帮助攻击者发送恶意请求
  • 显示伪造的文章或者图片

xss

上图的表单输入以后直接把输入内容当做 HTML 展示在页面上,所以存在着安全漏洞,攻击者可以直接在输入框内编辑危险的代码,然后就会在页面上运行。

11.2 SQL 注入攻击

SQL 注入(SQL Injection)是指针对 Web 应用使用的数据库,通过运行非法的 SQL 而产生的攻击。该安全隐患有可能引发极大的安全威胁,有时会直接导致个人信息及机密信息的泄露。

SQL 注入可能会导致如下影响:

  • 非法查看或篡改数据库内的数据
  • 规避认证
  • 执行和数据库服务器业务关联的程序等

如果我们不对输入进行验证就直接拿去拼接 SQL 的话,是可能会被执行 SQL 注入攻击的。

11.3 目录遍历攻击

目录遍历(Directory Traversal)攻击是指对本无意公开的文件目录,通过非法截断其目录路径后,达成访问目的的一种攻击。这种攻击有时也被叫做路径遍历攻击(Path Traversal)。

11.4 会话劫持

会话劫持(Session Hijack)是指攻击者通过某种手段拿到了用户的会话 ID,并非法使用此会话 ID 伪装成用户,达到攻击的目的。

具备认证功能的 Web 应用,使用会话 ID 的会话管理机制,作为管理认证状态的主流方式。会话 ID 中记录客户端的 Cookie 等信息,服务器端将会话 ID 与认证状态进行一对一匹配管理。

攻击者可能通过以下方式获得会话 ID:

  • 通过非正规的生成方法推测会话 ID
  • 通过窃听或 XSS 攻击盗取会话 ID
  • 通过会话固定攻击(Session Fixation)强行获取会话 ID

通常情况下攻击者在发现网站存在的 XSS 攻击漏洞之后,会注入一段 JavaScript 代码,通过 document.cookie 盗取到会话 ID,之后植入到自己的浏览器,就可以伪装成被盗窃的用户访问被攻击的网站。

11.5 跨站点请求伪造

跨站点请求伪造(Cross-Site Request Forgeries,CSRF)攻击是指攻击者通过设置好的陷阱,强制对已完成认证的用户进行非预期的个人信息或设定信息等某些状态更新,属于被动攻击。

最常见的例子就是在一个需要登录才能进行操作的网站,攻击者在该网站伪造了一个可以触发危险操作的内容(比如 a 和 button 标签),用户在不经意间点击这些伪造的内容后就自动发起了请求,而这些请求如果是指向当前网站的话,用户的会话 ID 等信息也会被带上,使得被攻击者不经意之间完成了一次可能极为危险的操作。

11.6 点击劫持

点击劫持(Clickjacking)是指利用透明的按钮或链接做成陷阱,覆盖在 Web 页面之上。然后诱导用户在不知情的情况下点击那个链接访问内容的一种攻击手段。这种行为又称为界面伪装(UI Redressing)。

这种攻击最常见的案例就是某些小网站……

11.7 DoS 攻击

DoS 攻击(Denial of Service Attack)是一种让运行中的服务呈停止状态的攻击。有时也叫作停止服务攻击或者拒绝服务攻击。DoS 攻击的对象不仅限于 Web 网站,还包括网络设备及服务器等。

DoS 主要有以下两种攻击方式:

  • 集中利用访问请求造成资源过载,资源用尽的同时,实际上服务也就呈停止状态
  • 通过攻击安全漏洞是服务停止

由此可见所有使得服务停止的攻击都可以称为 DoS 攻击。

DoS 攻击在中国前端届比较著名的案例就是阮一峰老师的博客遭到过的一次攻击:DDOS 攻击的防范教程