HTTP : Web 的基础
第一章 HTTP概述
Web客户端和服务器
客户端请求服务器内容
资源
媒体类型
MIME 类 型(MIME type)
Multipurpose Internet Mail Extension,多用途因特网邮件扩展
- HTML 格式的文本文档由 text/html 类型来标记。
- 普通的 ASCII 文本文档由 text/plain 类型来标记。
- JPEG 格式的图片为 image/jpeg 类型。
- GIF 格式的图片为 image/gif 类型。
- Apple 的 QuickTime 电影为 video/quicktime 类型。
- 微软的 PowerPoint 演示文件为 application/vnd.ms-powerpoint 类型。
URI
统一资源标识符(Uniform Resource Identifier,URI)
URL
统一资源定位符(URL)是资源标识符最常见的形式。URL描述了一台特定服务器上某资源的特定位置。
大部分 URL 都遵循一种标准格式,这种格式包含三个部分。
- URL 的第一部分被称为 方案(scheme),说明了访问资源所使用的协议类型。这
部分通常就是 HTTP 协议(http://)。 - 第二部分给出了服务器的因特网地址(比如, www.joes-hardware.com )。
- 其余部分指定了 Web 服务器上的某个资源(比如,/specials/saw-blade.gif)。
URN
统一资源名(URN)。URN 是作为特定内容的唯一名称使用
的,与目前的资源所在地无关。使用这些与位置无关的 URN,就可以将资源四处搬移。通过 URN,还可以用同一个名字通过多种网络访问协议来访问资源。
URN 仍然处于试验阶段,还未大范围使用。
事务
一个 HTTP 事务由一条(从客户端发往服务器的)请求命令和一个(从服务器发回客户端的)响应结果组成。
方法
状态码
复合 Web 页面要为每个嵌入式资源使用一个单独的 HTTP 事务
报文
链接
(Transmission Control Protocol,TCP)
HTTP 是个应用层协议。HTTP无需操心网络通信的具体细节;它把联网的细节都交给了通用、可靠的因特网传输协议 TCP/IP。
TCP 提供了:
- 无差错的数据传输;
- 按序传输(数据总是会按照发送的顺序到达);
- 未分段的数据流(可以在任意时刻以任意尺寸将数据发送出去)。
Telnet 的实例
Telnet 程序可以将键盘连接到某个目标 TCP 端口,并将此 TCP 端口的输出回送到显示屏上。Telnet常用于远程终端会话,但它几乎可以连接所有的 TCP 服务器,包括 HTTP 服务器。
协议版本
HTTP/1.1
Web的结构组件
- 代理
位于客户端和服务器之间的 HTTP 中间实体。 - 缓存
HTTP 的仓库,使常用页面的副本可以保存在离客户端更近的地方。 - 网关
连接其他应用程序的特殊 Web 服务器。 - 隧道
对 HTTP 通信报文进行盲转发的特殊代理。 - Agent 代理
发起自动 HTTP 请求的半智能 Web 客户端。
第二章 URL与资源
URL语法
URL http://www.joes-hardware.com/seasonal/index-fall.html
通用格式
几乎没有哪个 URL 中包含了所有这些组件。URL 最重要的 3 个部分是方案(scheme)、主机(host)和路径(path)。表 2-1 对各种组件进行了总结。
绝对 URL
相对 URL
解析相对URL
第三章 HTTP报文
报文流
HTTP 报文是在 HTTP应用程序之间发送的数据块。
这些数据块以一些文本形式的元信息(meta-information)开头。
报文流动
报文的组成部分
起始行和首部就是由行分隔的 ASCII 文本
方法
- GET
- HEAD
- POST
- TRACE
- OPTIONS
- DELETE
- 扩展方法
状态码
- 100~199 信息状态码
-
200~299 成功状态码
-
300~399 重定向状态码
-
400~499 客户端错误状态码
- 500~599 服务端错误状态码
首部
-
通用首部
-
请求首部
-
响应首部
-
实体首部
第四章 连接管理
TCP链接(传输控制协议)
TCP 的可靠数据管道
TCP 流是分段的、由 IP 分组传送
用 TCP 套接字编程
对TCP性能的考虑
HTTP 事务的时延
性能聚焦区域
- TCP 连接建立握手;
- TCP 慢启动拥塞控制;
- 数据聚集的 Nagle 算法;
- 用于捎带确认的 TCP 延迟确认算法;
- TIME_WAIT 时延和端口耗尽。
TCP 连接的握手时延
延迟确认
TCP 实现了自己的确认机制来确保数据的成功传输。
延迟确认算法会在一个特定的窗口时间(通常是 100 ~ 200 毫秒)内将输出确认存放在缓冲区中,以寻找能够捎带它的输出数据分组。如果在那个时间段内没有输出数据分组,就将确认信息放在单独的分组中传送。
TCP 慢启动
TCP 数据传输的性能还取决于 TCP 连接的使用期(age)。TCP 连接会随着时间进行自我“调谐”,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。
Nagle 算法与 TCP_NODELAY
Nagle 算法(根据其发明者 John Nagle 命名)试图在发送一个分组之前,将大量TCP 数据绑定在一起,以提高网络效率。
Nagle 算法鼓励发送全尺寸(LAN 上最大尺寸的分组大约是 1500 字节,在因特网上是几百字节)的段。
延迟确认算法延迟 100 ~ 200 毫秒。
HTTP 应用程序常常会在自己的栈中设置参数 TCP_NODELAY,禁用 Nagle 算法,提高性能。如果要这么做的话,一定要确保会向 TCP 写入大块的数据,这样就不会产生一堆小分组了。
TIME_WAIT 累积与端口耗尽
当某个 TCP 端点关闭 TCP 连接时,会在内存中维护一个小的控制块,用来记录最近所关闭连接的 IP 地址和端口号。这类信息只会维持一小段时间,通常是所估计的最大分段使用期的两倍(称为 2MSL,通常为 2 分钟 8 )左右,以确保在这段时间内不会创建具有相同地址和端口号的新连接。
客户端每次连接到服务器上去时,都会获得一个新的源端口,以实现连接的唯一性。但由于可用源端口的数量有限(比如,60 000 个),而且在 2MSL 秒(比如,120秒)内连接是无法重用的,连接率就被限制在了 60 000/120=500 次 / 秒。如果再不断进行优化,并且服务器的连接率不高于 500 次 / 秒,就可确保不会遇到 TIME_WAIT 端口耗尽问题。
HTTP连接的处理
常被误解的 Connection 首部
并行连接
持久连接
HTTP/1.1(以及 HTTP/1.0 的各种增强版本) 允许 HTTP 设备在事务处理结束之后将 TCP 连接保持在打开状态,以便为未来的 HTTP 请求重用现存的连接。在事务处理结束之后仍然保持在打开状态的 TCP 连接被称为持久连接。
持久以及并行连接
HTTP/1.0+ keep-alive 连接
HTTP/1.1 持久连接
HTTP/1.1 逐 渐 停 止 了 对 keep-alive 连 接 的 支 持, 用 一 种 名 为持 久 连 接(persistent connection)的改进型设计取代了它。持久连接的目的与 keep-alive 连接的目的相同,但工作机制更优一些。
管道化连接
在响应到达之前,可以将多条请求放入队列。当第一条请求通过网络流向地球另一端的服务器时,第二条和第三条请求也可以开始发送了。在高时延网络条件下,这样做可以降低网络的环回时间,提高性能。
必须按照与请求相同的顺序回送 HTTP 响应。
HTTP 客户端不应该用管道化的方式发送会产生副作用的请求(比如 POST )。
关闭连接的奥秘
- “任意”解除连接
- Content-Length 及截尾操作
- 连接关闭容限、重试以及幂等性
- 正常关闭连接
链接类型(MDN web docs)
What can be controlled by HTTP
Here is a list of common features controllable with HTTP.
Caching
How documents are cached can be controlled by HTTP. The server can instruct proxies and clients, about what to cache and for how long. The client can instruct intermediate cache proxies to ignore the stored document.Relaxing the origin constraint
To prevent snooping and other privacy invasions, Web browsers enforce strict separation between Web sites. Only pages from the same origin can access all the information of a Web page. Though such constraint is a burden to the server, HTTP headers can relax this strict separation on the server side, allowing a document to become a patchwork of information sourced from different domains; there could even be security-related reasons to do so.
- Authentication
Some pages may be protected so that only specific users can access them. Basic authentication may be provided by HTTP, either using the WWW-Authenticate and similar headers, or by setting a specific session using HTTP cookies.
- Proxy and tunneling
Servers or clients are often located on intranets and hide their true IP address from other computers. HTTP requests then go through proxies to cross this network barrier. Not all proxies are HTTP proxies. The SOCKS protocol, for example, operates at a lower level. Other protocols, like ftp, can be handled by these proxies.
- Sessions
Using HTTP cookies allows you to link requests with the state of the server. This creates sessions, despite basic HTTP being a state-less protocol. This is useful not only for e-commerce shopping baskets, but also for any site allowing user configuration of the output.
Web服务器
各种形状和尺寸的 Web 服务器
“Web 服务器”可以用来表示 Web 服务器的软件,也可以用来表示提供 Web 页面的特定设备或计算机。
Web 服务器的实现
Web 服务器实现了 HTTP 和相关的 TCP 连接处理。负责管理 Web 服务器提供的资源,以及对 Web 服务器的配置、控制及扩展方面的管理。
通用软件 Web 服务器
Web 服务器设备
嵌入式 Web 服务器
最小的 Perl Web 服务器
实际的 Web 服务器会做些什么
(1) 建立连接——接受一个客户端连接,或者如果不希望与这个客户端建立连接,就将其关闭。
(2) 接收请求——从网络中读取一条 HTTP 请求报文。
(3) 处理请求——对请求报文进行解释,并采取行动。
(4) 访问资源——访问报文中指定的资源。
(5) 构建响应——创建带有正确首部的 HTTP 响应报文。
(6) 发送响应——将响应回送给客户端。
(7) 记录事务处理过程——将与已完成事务有关的内容记录在一个日志文件中。
第一步——接受客户端连接
如果客户端已经打开了一条到服务器的持久连接,可以使用那条连接来发送它的
请求。否则,客户端需要打开一条新的到服务器的连接。
第二步——接收请求报文
连接上有数据到达时,Web 服务器会从网络连接中读取数据,并将请求报文中的内容解析出来(参见图 5-5)。
解析请求报文时,Web 服务器会:
- 解析请求行,查找请求方法、指定的资源标识符(URI)以及版本号, 各项之间由一个空格分隔,并以一个回车换行(CRLF)序列作为行的结束;
- 读取以 CRLF 结尾的报文首部;
- 检测到以 CRLF 结尾的、标识首部结束的空行(如果有的话);
- 如果有的话(长度由 Content-Length 首部指定),读取请求主体。
解析请求报文时,Web 服务器会不定期地从网络上接收输入数据。网络连接可能随
时都会出现延迟。Web 服务器需要从网络中读取数据,将部分报文数据临时存储在
内存中,直到收到足以进行解析的数据并理解其意义为止。
报文的内部表示法
有些 Web 服务器还会用便于进行报文操作的内部数据结构来存储请求报文。
连接的输入 / 输出处理结构
- 单线程 Web 服务器
- 多进程及多线程 Web 服务器
- 复用 I/O 的服务器
-
复用的多线程 Web 服务器
第三步——处理请求
第四步——对资源的映射及访问
docroot
在配置文件 httpd.conf 中添加一个 DocumentRoot 行就可以为 Apache Web 服务器
设置文档的根目录了:
DocumentRoot /usr/local/httpd/files
虚拟托管的 docroot
虚拟托管的 Web 服务器会在同一台 Web 服务器上提供多个 Web 站点,每个站点在
服务器上都有自己独有的文档根目录。
图 5-9 中的服务器托管了两个站点:www.joes-hardware.com 和 www.marys-antiques.
com。服务器可以通过 HTTP 的 Host 首部,或根据不同的 IP 地址来区分不同的Web 站点。
- 当请求 A 到达时,服务器会获取文件 /docs/joe/index.html。
- 当请求 B 到达时,服务器会获取文件 /docs/mary/index.html。
Apache Web 服务器虚拟主机的 docroot 配置
ServerName www.joes-hardware.com
DocumentRoot /docs/joe
TransferLog /logs/joe.access_log
ErrorLog /logs/joe.error_log
ServerName www.marys-antiques.com
DocumentRoot /docs/mary
TransferLog /logs/mary.access_log
ErrorLog /logs/mary.error_log
...
用户的主目录 docroot
Docroot 的另一种常见应用是在 Web 服务器上为人们提供私有的 Web 站点。通常会把那些以斜杠和波浪号( /~ )开始,后面跟着用户名的 URI 映射为此用户的私有文档根目录。
第五步——构建响应
一旦 Web 服务器识别出了资源,就执行请求方法中描述的动作,并返回响应报文。响应报文中包含有响应状态码、响应首部,如果生成了响应主体的话,还包括响应主体。
响应实体
- 描述了响应主体 MIME 类型的 Content-Type 首部;
- 描述了响应主体长度的 Content-Length 首部;
- 实际报文的主体内容。
MIME 类型
Web 服务器要负责确定响应主体的 MIME 类型。
重定向
- 永久搬离的资源
- 临时搬离的资源
- URL 增强
- 负载均衡
- 服务器关联
- 规范目录名称
第六步——发送响应
第七步——记录日志
代理
6.1 Web 的中间实体
6.1.1 私有和共享代理
6.1.2 代理与网关的对比
代理连接的是两个或多个使用相同协议的应用程序,而网关连接的则是两个或多个使用不同协议的端点。网关扮演的是“协议转换器”的角色,即使客户端和服务器使用的是不同的协议,客户端也可以通过它完成与服务器之间的事务处理。
6.2 为什么使用代理
-
儿童过滤器
-
文档访问控制
代理服务器在大量 Web 服务器和 Web 资源之间实现统一的访问控制策略,创建审核跟踪机制。
在集中式代理服务器上可以对所有访问控制功能进行配置,而无需在众多由不同组织管理、不同厂商制造、使用不同模式的Web服务器上进行经常性的访问控制升级。
-
安全防火墙
代理服务器会在网络中的
单一安全节点上限制哪些应用层协议的数据可以流入或流出一个组织。还可以提供用来消除病毒的 Web 和 E-mail 代理使用的那种挂钩程序,以便对流量进行详细的检查。
Web 缓存
-
反向代理
正向代理中,proxy和client同属一个LAN,对server透明;反向代理中,proxy和server同属一个LAN,对client透明。实际上proxy在两种代理中做的事都是代为收发请求和响应,不过从结构上来看正好左右互换了下,所以把后出现的那种代理方式叫成了反向代理。
-
内容路由器
代理服务器可以作为“内容路由器”使用,根据因特网流量状况以及内容类型将请求导向特定的 Web 服务器。
-
转码器
代理服务器在将内容发送给客户端之前,可以修改内容的主体格式。
转码代理可以在传输 GIF 图片时,将其转换成 JPEG 图片,以减小尺寸。
-
匿名者
从 User-Agent 首部删除用户的计算机与 OS 类型。
删除 From 首部以保护用户的 E-mail 地址。
删除 Referer 首部来掩盖用户访问过的其他站点。
删除 Cookie 首部以剔除概要信息和身份的数据。
匿名者代理会主动从 HTTP 报文中删除身份特性(比如客户端 IP 地址、 From首 部、 Referer 首 部、cookie、URI 的 会 话 ID), 从 而 提 供 高 度 的 私 密 性 和 匿名性。
6.3 代理会去往何处
6.3.1 代理服务器的部署
- 出口代理
- 访问(入口)代理
- 反向代理
-
网络交换代理
6.3.2 代理的层次结构
6.3.3 代理是如何获取流量的
- 修改客户端
- 修改网络
- 修改 DNS 的命名空间
-
修改 Web 服务器
6.4 客户端的代理设置
- 手工配置
- 预先配置浏览器
- 代理的自动配置 (Proxy Auto-Configuration,PAC)
- WPAD 的代理发现
6.5 与代理请求有关的一些棘手问题
...
6.6 追踪报文
6.6.1 Via 首部
Via 首部字段列出了与报文途经的每个中间节点(代理或网关)有关的信息。报文每经过一个节点,都必须将这个中间节点添加到 Via 列表的末尾。
Via: 1.1 proxy-62.irenes-isp.net, 1.0 cache.joes-hardware.com
Via 的请求和响应路径
Via 与网关
有些代理会为使用非 HTTP 协议的服务器提供网关的功能。 Via 首部记录了这些协议转换,这样, HTTP 应用程序就会了解代理链上各点的协议处理能力以及所做的协议转换了。图 6-22 显示了一个通过 HTTP/FTP 网关请求某个 FTP URI 的 HTTP
客户端。
Via 的隐私和安全问题
我们并不希望在 Via 字符串中使用确切的主机名。
对那些有着非常强烈的隐私要求,需要隐藏内部网络设计和拓扑结构的组织来说,代理应该将一个(接收协议值相同的)有序 Via 路标条目序列合并成一个联合条目。比如,可以将:
Via: 1.0 foo, 1.1 devirus.company.com, 1.1 access-logger.company.com
压缩成:
Via: 1.0 foo, 1.1 concealed-stuff
6.6.2 TRACE 方法
通过 HTTP/1.1 的 TRACE 方法,用户可以跟踪经代理链传输的请求报文,观察报文经过了哪些代理,以及每个代理是如何对请求报文进行修改的。
- Max-Forwards
TRACE 报文都会沿着整条路径传到目的服务器上。可以使用 Max-Forwards (最大转发次数)首部来限制 TRACE 和 OPTIONS请求所经过的代理跳数,在测试 代理 链是否是在无限循环中转发报文,或者查看链中特定代理服务器的效果时,它是很有用的。
如果 Max-Forwards 的值为零( Max-Forwards:0 ),那么即使接收者不是原始服务器,它也必须将 TRACE 报文回送给客户端,而不应该继续转发。
6.7 代理认证
代 理 可 以 作 为 访 问 控 制 设 备 使 用。HTTP 定 义 了 一 种 名 为 代 理 认 证(proxyauthentication)的机制,这种机制可以阻止对内容的请求,直到用户向代理提供了
有效的访问权限证书为止。
6.8 代理的互操作性
6.8.1 处理代理不支持的首部和方法
6.8.2 OPTIONS :发现对可选特性的支持
如果 OPTIONS 请求的 URI 是个星号( * ),请求的就是整个服务器所支持的功能。比如:
OPTIONS * HTTP/1.1
如果 URI 是个实际资源地址,OPTIONS 请求就是在查询那个特定资源的可用特性:
OPTIONS http://www.joes-hardware.com/index.html HTTP/1.1
6.8.3 Allow首部
Allow 实体首部字段列出了请求 URI 标识的资源所支持的方法列表,如果请求 URI为 * 的话,列出的就是整个服务器所支持的方法列表。
Allow: GET, HEAD, PUT
可以将 Allow 首部作为请求首部,建议在新的资源上支持某些方法。并不要求服务器支持这些方法,但应该在相应的响应中包含一个 Allow 首部,列出它实际支持的方法。
缓存
冗余的数据传输
带宽瓶颈
瞬间拥塞
距离时延
每台网络路由器都会增加因特网流量的时延。即使客户端和服务器之间没有太多的路由器,光速自身也会造成显著的时延。
波士顿到旧金山的直线距离大约有2700英里。在最好的情况下,以光速传输(186000英里/秒)的信号可以在大约15毫秒内从波士顿传送到旧金山,并在30毫秒内完成一个往返。
命中和未命中的
再验证(新鲜度检测)revalidation
原始服务器的内容可能会发生变化,缓存要不时对其进行检测,看看它们保存的副本是否仍是服务器上最新的副本。
命中率
文档命中率
40% 的命中率是很合理的
字节命中率
缓存的拓扑结构
私有缓存
公有代理缓存
代理缓存的层次结构
网状缓存
有些网络结构会构建复杂的网状缓存(cache mesh),而不是简单的缓存层次结构。
内容路由
代理缓存会决定选择何种路由对内容进行访问、管理和传送,因此可将其称为内容路由器(content router)
- 根据 URL 在父缓存或原始服务器之间进行动态选择。
- 根据 URL 动态地选择一个特定的父缓存。
- 前往父缓存之前,在本地缓存中搜索已缓存的副本。
- 允许其他缓存对其缓存的部分内容进行访问,但不允许因特网流量通过它们的
缓存。
对等缓存
缓存之间这些更为复杂的关系允许不同的组织互为对等(peer)实体,将它们的缓存连接起来以实现共赢。提供可选的对等支持的缓存被称为兄弟缓存(siblingcache)
缓存的处理步骤
(1) 接收——缓存从网络中读取抵达的请求报文。
(2) 解析——缓存对报文进行解析,提取出 URL 和各种首部。
(3) 查询——缓存查看是否有本地副本可用,如果没有,就获取一份副本(并将其保存在本地)。
(4) 新鲜度检测——缓存查看已缓存副本是否足够新鲜,如果不是,就询问服务器是否有任何更新。
(5) 创建响应——缓存会用新的首部和已缓存的主体来构建一条响应报文。
(6) 发送——缓存通过网络将响应发回给客户端。
(7) 日志——缓存可选地创建一个日志文件条目来描述这个事务。
新鲜度检测
缓存可以在不联系服务器的情况下,直接提供该文档。但一旦已缓存副本停留的时间太长,超过了文档的新鲜度限值(freshness limit),就认为对象“过时”了,在提供该文档之前,缓存要再次与服务器进行确认,以查看文档是否发生了变化。客户端发送给缓存的所有请求首部自身都可以强制缓存进行再验证,或者完全避免验证,这使得事情变得更加复杂了。
保持副本的新鲜
文档会随着时间发生变化。
HTTP 有一些简单的机制可以在不要求服务器记住有哪些缓存拥有其文档副本的情况下,保持已缓存数据与服务器数据之间充分一致。HTTP 将这些简单的机制称为文档过期(document expiration)和服务器再验证(server revalidation)。
文档过期
HTTP Cache-Control 首部 和 Expires 首部
服务器再验证
• 如果再验证显示内容 发生了变化,缓存会获取一份新的文档副本,并将其存储在旧文档的位置上,然后将文档发送给客户端。
• 如果再验证显示内容 没有发生变化,缓存只需要获取新的首部,包括一个新的过期日期,并对缓存中的首部进行更新就行了。
缓存并不一定要为每条请求验证文档的有效性——只有在文档过期时它才需要与服务器进行再验证。这样不会提供陈旧的内容,还可以节省服务器的流量,并拥有更好的用户响应时间。
用条件方法进行再验证
HTTP 的条件方法可以高效地实现再验证。HTTP 允许缓存向原始服务器发送一个“条件 GET”,请求服务器只有在文档与缓存中现有的副本不同时,才回送对象主体。
If-Modified-Since:Date 再验证
If-Modified-Since 再验证请求通常被称为 IMS 请求。只有自某个日期之后资源发生了变化的时候,IMS 请求才会指示服务器执行请求:
- 如果自指定日期后,文档被修改了, If-Modified-Since 条件就为真,通常GET 就会成功执行。携带新首部的新文档会被返回给缓存,新首部除了其他信息之外,还包含了一个新的过期日期。
- 如 果 自 指 定 日 期 后, 文 档 没 被 修 改 过, 条 件 就 为 假, 会 向 客 户 端 返 回 一 个 小的 304 Not Modified 响应报文,为了提高有效性,不会返回文档的主体。 这些首部是放在响应中返回的,但只会返回那些需要在源端更新的首部。比如,Content-Type 首部通常不会被修改,所以通常不需要发送。一般会发送一个新的过期日期。
If-Modified-Since 首部可以与 Last-Modified 服务器响应首部配合工作。原始服务器会将最后的修改日期附加到所提供的文档上去。当缓存要对已缓存文档进行再验证时,就会包含一个 If-Modified-Since 首部,其中携带有最后修改已缓存副本的日期:
If-Modified-Since:
假设今天是美国东部标准时间(EST,Eastern Standard Time)2002 年 6 月 29 日上午 9 ∶ 30 , Joe 的五金商店正在准备进行 7 月 4 日(美国国庆日)特卖(只剩 5 天了)。 Joe 想在他的 Web 服务器上放置一个特殊的 Web 页面,并将其设置为 2002 年7 月 5 日晚上的 EST 午夜时间过期。如果 Joe 的服务器使用的是老式的 Expires 首部,服务器响应报文(参见图 7-13a)中可能就会包含这个首部:
Expires: Fri, 05 Jul 2002, 05:00:00 GMT
如果 Joe 的服务器使用了较新的 Cache-Control: max-age 首部,服务器响应报文
(参见图 7-13b)中可能就会包含这个首部:Cache-Control: max-age=484200如果这还不够明确的话,可以这样来看,当前时间,EST 时间 2002 年 6 月 29 日早上9∶30,到售卖结束时间 2002 年 7 月 5 日午夜之间有 484 200 秒。到售卖结束之前还有 134.5 小时(大约 5 天)。每小时有 3600 秒,这样到售卖结束之前还有 484 200 秒。
例如,如图 7-14 所示,如果你的缓存在 7 月 3 日对 Joe 的五金商店的 7 月 4 日特卖声明进行再验证,就会收到一条 Not Modified 响应(参见图 7-14a)。但如果你的缓存在 7 月 5 日午夜售卖结束后对文档进行再验证,缓存就会收到一个新文档,因为服务器内容已经发生了变化(参见图 7-14b)。
If-None-Match:实体标签再验证
有些情况下仅使用最后修改日期进行再验证是不够的。
- 有些文档可能会被周期性地重写(比如,从一个后台进程中写入),但实际包含的数据常常是一样的。尽管内容没有变化,但修改日期会发生变化。
- 有些文档可能被修改了,但所做修改并不重要,不需要让世界范围内的缓存都重装数据(比如对拼写或注释的修改)。
- 有些服务器无法准确地判定其页面的最后修改日期。
- 有些服务器提供的文档会在亚秒间隙发生变化(比如,实时监视器),对这些服务器来说,以一秒为粒度的修改日期可能就不够用了。
为了解决这些问题, HTTP 允许用户对被称为实体标签( ETag )的“版本标识符”
进行比较。
如果服务器上的实体标签已经发生了变化(可能变成了 v3.0 ),服务器会在一个 200
OK 响应中返回新的内容以及相应的新 Etag 。
强弱验证器
服务器希望在对文档进行一些非实质性或不重要的修改时,不要使所有的已缓存副本都失效。HTTP/1.1 支持“弱验证器”,如果只对内容进行了少量修改,就允许服务器声明那是“足够好”的等价体。
只要内容发生了变化,强验证器就会变化。弱验证器允许对一些内容进行修改,但内容的主要含义发生变化时,通常它还是会变化的。有些操作不能用弱验证器来实现(比如有条件地获取部分内容),所以,服务器会用前缀“W/”来标识弱验证器。
ETag: W/"v2.6"
If-None-Match: W/"v2.6
什么时候应该使用实体标签和最近修改日期
如果服务器回送了一个实体标签,HTTP/1.1 客户端就必须使用实体标签验证器。如果服务器只回送了一个 Last-Modified 值,客户端就可以使用 If-Modified-Since验证。如果实体标签和最后修改日期都提供了,客户端就应该使用这两种再验证方案,这样HTTP/1.0 和 HTTP/1.1 缓存就都可以正确响应了。
控制缓存的能力
- 附加一个 Cache-Control: no-store 首部到响应中去;
- 附加一个 Cache-Control: no-cache 首部到响应中去;
Pragma: no-cache
Cache-Control: no-store
Cache-Control: no-cache
标识为 no-store 的响应会禁止缓存对响应进行复制。缓存通常会像非缓存代理服务器一样,向客户端转发一条 no-store 响应,然后删除对象。
标识为 no-cache 的响应实际上是可以存储在本地缓存区中的。只是在与原始服务器进行新鲜度再验证之前,缓存不能将其提供给客户端使用。
- 附加一个 Cache-Control: must-revalidate 首部到响应中去;
Cache-Control: must-revalidate
Cache-Control: must-revalidate 响应首部告诉缓存,在事先没有跟原始服务器进行再验证的情况下,不能提供这个对象的陈旧副本。
- 附加一个 Cache-Control: max-age 首部到响应中去;
Cache-Control: max-age=3600
Cache-Control: s-maxage=3600
- 附加一个 Expires 日期首部到响应中去;
Expires: Fri, 05 Jul 2002, 05:00:00 GMT
- 附加过期信息,让缓存确定自己的过期日期。
试探性过期
如果响应中没有 Cache-Control: max-age 首部,也没有 Expires 首部,缓存可以计算出一个试探性最大使用期
LM-Factor 算法是一种很常用的试探性过期算法,如果文档中包含了最后修改日期,就可以使用这种算法。LM-Factor 算法将最后修改日期作为依据,来估计文档有多么易变。算法的逻辑如下所示。
- 如果已缓存文档最后一次修改发生在很久以前,它可能会是一份稳定的文档,不
太会突然发生变化,因此将其继续保存在缓存中会比较安全。 - 如果已缓存文挡最近被修改过,就说明它很可能会频繁地发生变化,因此在与服
务器进行再验证之前,只应该将其缓存很短一段时间。
客户端的新鲜度限制
设置缓存控制
控制 Apache 的 HTTP 首部
- mod_headers
Header set Cache-control no-cache
- mod_expires
ExpiresDefault A3600
ExpiresDefault M86400
ExpiresDefault "access plus 1 week"
ExpiresByType text/html "modification plus 2 days 6 hours 12 minutes"
- mod_cern_meta
通过 HTTP-EQUIV 控制 HTML 缓存
My Document
...
总之,< META HTTP-EQUIV > 标签并不是控制文档缓存特性的好方法。通过配置正确的服务器发出 HTTP 首部,是传送文档缓存控制请求的唯一可靠的方法。
详细算法
缓存和广告
Freshness (新鲜度)
As HTTP is a client-server protocol, servers can't contact caches and clients when a resource changes; they have to communicate an expiration time for the resource. Before this expiration time, the resource is fresh; after the expiration time, the resource is stale.
Here is an example of this process with a shared cache proxy:
第八章 集成点:网关、隧道及中继
Web 浏览器这样的 HTTP 应用程序为用户提供了一种统一的方式来访问因特网上的内容。
HTTP 也已成为应用程序开发者的一种基本构造模块,开发者们可以在 HTTP 上捎回其他的协议内容(比如,可以将其他协议的流量包裹在 HTTP 中,用 HTTP 通过隧道或中继方式将这些流量传过公司的防火墙)。Web 上所有的资源都可以使用 HTTP 协议,而且其他应用程序和应用程序协议也可以利用 HTTP 来完成它们的任务。
本章简要介绍了一些开发者用 HTTP 访问不同资源的方法,展示了开发者如何将HTTP 作为框架启动其他协议和应用程序通信。
8.1 网关
HTTP 扩展和接口的发展是由用户需求驱动的。要在 Web 上发布更复杂资源的需求出现时,人们很快就明确了一点:单个应用程序无法处理所有这些能想到的资源。
为了解决这个问题,开发者提出了网关(gateway)的概念,网关可以作为某种翻译器使用,它抽象出了一种能够到达资源的方法。网关是资源和应用程序之间的粘合剂。应用程序可以(通过 HTTP 或其他已定义的接口)请求网关来处理某条请求,网关可以提供一条响应。网关可以向数据库发送查询语句,或者生成动态的内容,就像一个门一样:进去一条请求,出来一个响应。
图 8-1 显示的是一种资源网关。在这里,Joe 的五金商店服务器就是作为连接数据库内容的网关使用的——注意,客户端只是在通过 HTTP 请求资源,而 Joe 的五金商店的服务器在与网关进行交互以获取资源。
图 8-2 显示了三个网关的示例。
在图 8-2a 中,网关收到了对 FTP URL 的 HTTP 请求。然后网关打开 FTP 连接,并向 FTP 服务器发布适当的命令。然后将文档和正确的 HTTP 首部通过 HTTP回送。
在图 8-2b 中,网关通过 SSL 收到了一条加密的 Web 请求,网关会对请求进行解密, 1 然后向目标服务器转发一条普通的 HTTP 请求。可以将这些安全加速器直接放在(通常处于同一场所的)Web 服务器前面,以便为原始服务器提供高性能的加密机制。
-
在图 8-2c 中,网关通过应用程序服务器网关 API,将 HTTP 客户端连接到服务器端的应用程序上去。在网上的电子商店购物、查看天气预报,或者获取股票报价时,访问的就是应用程序服务器网关。
客户端和服务器端网关
可以用一个斜杠来分隔客户端和服务器端协议,并以此对网关进行描述:
< 客户端协议 >/< 服务器端协议 >
我们用术语服务器端网关和客户端网关来说明对话是在网关的哪一侧进行的。
- 服务器端网关 (server-side gateway)通过 HTTP 与客户端对话,通过其他协议与服务器通信(HTTP/ * )。
- 客户端网关 (client-side gateway)通过其他协议与客户端对话,通过 HTTP 与服务器通信( * /HTTP)。
8.2 协议网关
图 8-3 显示了配置浏览器使用服务器端 FTP 网关的对话框。在图中显示的配置中,配置浏览器将 gw1.joes-hardware.com 作为所有 FTP URL 的 HTTP/FTP 网关。浏览器没有将 FTP 命令发送给 FTP 服务器,而是将 HTTP 命令发送给端口 8080 上的HTTP/FTP 网关 gw1.joes-hardware.com。
8.2.1 HTTP/* :服务器端 Web 网关
请求流入原始服务器时,服务器端 Web 网关会将客户端 HTTP 请求转换为其他协议。
在图 8-5 中,网关收到了一条对 FTP 资源的 HTTP 请求:
ftp://ftp.irs.gov/pub/00-index.txt
网关会打开一条到原始服务器 FTP 端口(端口 21)的 FTP 连接,通过 FTP 协议获
取对象。
8.2.2 HTTP/HTTPS :服务器端安全网关
8.2.3 HTTPS/HTTP 客户端安全加速器网关
这些网关中通常都包含专用的解密硬件,以比原始服务器有效得多的方式来解密安全流量,以减轻原始服务器的负荷。
8.3 资源网关
应用程序服务器,会将目标服务器与网关结合在一个服务器中实现。应用程序服务器是服务器端网关,与客户端通过 HTTP 进行通信,并与服务器端的应用程序相连。
两 个 客 户 端 是 通 过 HTTP 连 接 到 应 用 程 序 服 务 器 的。 但 应 用 程 序服 务 器 并 没 有 回 送 文 件, 而 是 将 请 求 通 过 一 个 网 关 应 用 编 程 接 口(ApplicationProgramming Interface,API)发送给运行在服务器上的应用程序。
第一个流行的应用程序网关 API 就是通用网关接口(Common Gateway Interface,
CGI)。CGI 是 一 个 标 准 接 口 集,Web 服 务 器 可 以 用 它 来 装 载 程 序 以 响 应 对 特 定URL 的 HTTP 请求,并收集程序的输出数据,将其放在 HTTP 响应中回送。
8.3.1 CGI
CGI 是第一个,可能仍然是得到最广泛使用的服务器扩展。在 Web 上广泛用于动态HTML 、信用卡处理以及数据库查询等任务。
它在服务器和众多的资源类型之间提供了一种简单的、函数形式的粘合方式,用来处理各种需要的转换。这个接口还能很好地保护服务器,防止一些糟糕的扩展对它造成的破坏。
8.3.2 服务器扩展 API
扩展 API 允许程序员将自己的代码嫁接到服务器上,或者用自己的代码将服务器的一个组件完整地替换出来。
8.4 应用程序接口和 Web 服务
将资源网关作为 Web 服务器与应用程序的通信方式使用。
随着 Web 应用程序提供的服务类型越来越多,有一点变得越来越清晰了:HTTP 可以作为一种连接应用程序的基础软件来使用。
因特网委员会开发了一组允许 Web 应用程序之间相互通信的标准和协议。尽管 Web
服务(Web service)可以用来表示独立的 Web 应用程序(构造模块),这里我们还是宽松地用这个术语来表示这些标准。
8.5 隧道
Web 隧道允许用户通过 HTTP 连接发送非 HTTP 流量,这样就可以在 HTTP 上捎带其他协议数据了。使用 Web 隧道最常见的原因就是要在 HTTP 连接中嵌入非 HTTP
流量,这样,这类流量就可以穿过只允许 Web 流量通过的防火墙了。
8.5.1 用 CONNECT 建立 HTTP 隧道
CONNECT 方法请求隧道网关创建一条到达任意目的服务器和端口的 TCP 连接,并对客户端和服务器之间的后继数据进行盲转发。
8.5.2 数据隧道、定时及连接管理
8.5.3 SSL 隧道
Web 隧道是为了通过防火墙来传输加密的 SSL 流量。很多组织都会将所有流量通过分组过滤路由器和代理服务器以隧道方式传输,以提升安全性。但有些协议,比如加密 SSL,其信息是加密的,无法通过传统的代理服务器转发。隧道会通过一条 HTTP 连接来传输 SSL 流量,以穿过端口 80 的 HTTP 防火墙(参见图 8-11)。
8.5.4 SSL 隧道与 HTTP/HTTPS 网关的对比
缺点:
- 客户端到网关之间的连接是普通的非安全 HTTP;
- 尽管代理是已认证主体,但客户端无法对远端服务器执行 SSL 客户端认证(基
于 X509 证书的认证); - 网关要支持完整的 SSL 实现。
8.5.5 隧道认证
将代理的认证支持与隧道配合使用,对客户端使用隧道的权利进行认证(参见图 8-13)。
8.5.6 隧道的安全性考虑
为了降低对隧道的滥用,网关应该只为特定的知名端口,比如 HTTPS 的端口 443,打开隧道。
8.6 中继
HTTP 中继(relay)是没有完全遵循 HTTP 规范的简单 HTTP 代理。中继负责处HTTP 中建立连接的部分,然后对字节进行盲转发。
第九章 Web 机器人
9.6 搜索引擎
9.6.3 全文索引
全文索引就是一个数据库,给它一个单词,它可以立即提供包含那个单词的所有文档。创建了索引之后,就不需要对文档自身进行扫描了。
第十章 HTTP-NG
- 第一层, 报文传输层(message transport layer),这一层不考虑报文的功能,而是致力于端点间报文的不透明传输。报文传输层支持各种子协议栈(比如无线环境下的协议栈),主要负责处理高效报文传输及处理方面的问题。HTTP-NG 项目组为本层提出了一个名为 WebMUX 的协议。
- 第二层, 远程调用层(remote invocation layer),定义了请求 / 响应的功能,客户端可以通过这些功能调用对服务器资源的操作。本层独立于报文的传输以及操作的精确语义。它只是提供了一种标准的方法来调用服务器上所有的操作。本层试图提供一种像 CORBA、DCOM 和 Jave RMI 那样的面向对象的可扩展框架,而不是 HTTP/1.1 中那种静态的、服务器端定义的方法。HTTP-NG 项目组建议本层使用二进制连接协议(Binary Wire Protocol)。
- 第三层, Web 应用层(Web application layer),提供了大部分的内容管理逻辑。所有的 HTTP/1.1 方法(GET、POST、PUT 等),以及 HTTP/1.1 首部参数都是在这里定义的。本层还支持其他构建在远程调用基础上的服务,比如 WebDAV。
第三部分 识别、认证与安全
第十一章 客户端识别与 cookie 机制
Web 服务器可能会同时与数千个不同的客户端进行对话。这些服务器通常要记录下它们在与谁交谈,而不会认为所有的请求都来自匿名的客户端。本章讨论了一些服务器可以用来识别其交谈对象的技巧。
11.1 个性化接触
HTTP 最初是一个匿名、无状态的请求 / 响应协议。服务器处理来自客户端的请求,然后向客户端回送一条响应。
用户识别机制
- 承载用户身份信息的 HTTP 首部。
- 客户端 IP 地址跟踪,通过用户的 IP 地址对其进行识别。
- 用户登录,用认证方式来识别用户。
- 胖 URL,一种在 URL 中嵌入识别信息的技术。
- cookie,一种功能强大且高效的持久身份识别技术。
11.6 cookie
cookie 是当前识别用户,实现持久会话的最好方式。
11.6.1 cookie 的类型
- 会 话 cookie
- 持 久 cookie
11.6.2 cookie 是如何工作的
cookie 就像服务器给用户贴的“嗨,我叫”的贴纸一样。用户访问一个 Web 站点时,这个 Web 站点就可以读取那个服务器贴在用户身上的所有贴纸。
cookie 中包含了一个由名字 = 值(name=value)这样的信息构成的任意列表,并通过 Set-Cookie 或 Set-Cookie2 HTTP 响应(扩展)首部将其贴到用户身上去。
11.6.3 cookie 罐:客户端的状态
cookie 的基本思想就是让浏览器积累一组服务器特有的信息,每次访问服务器时都将这些信息提供给它。
-
网景的 Navigator 的 cookie
-
微软 Internet Explorer 的 cookie
11.6.4 不同站点使用不同的 cookie
- cookie 的域属性
产生 cookie 的服务器可以向 Set-Cookie 响应首部添加一个 Domain 属性来控制哪些站点可以看到那个 cookie。
Set-cookie: user="mary17"; domain="airtravelbargains.com"
如果用户访问的是 www.airtravelbargains.com、specials.airtravelbargains.com 或意
以 .airtravelbargains.com 结尾的站点,下列 Cookie 首部都会被发布出去:
Cookie: user="mary17" - cookie 路径属性
cookie 规范甚至允许用户将 cookie 与部分 Web 站点关联起来。可以通过 Path 属性来实现这一功能,在这个属性列出的 URL 路径前缀下所有 cookie 都是有效的。
11.6.5 cookie 成分
cookies 版本 0(有时被称为 Netscapecookies) 和 cookies 版 本 1(RFC 2965)。cookies 版 本 1 是 对 cookies 版 本 0 的 扩展,应用不如后者广泛。
11.6.6 cookies 版本 0 ( Netscape )
Set-Cookie: name=value [; expires=date] [; path=path] [; domain=domain]
[; secure]
Cookie: name1=value1 [; name2=value2] ...
11.6.7 cookies 版本 1 ( RFC 2965 )
RFC 2965 cookie 标准比原始的网景公司的标准略微复杂一些,还未得到完全的支持。RFC 2965 cookie 的主要改动包括下列内容。
- 为每个 cookie 关联上解释性文本,对其目的进行解释。
- 允许在浏览器退出时,不考虑过期时间,将 cookie 强制销毁。
- 用相对秒数,而不是绝对日期来表示 cookie 的 Max-Age 。
- 通过 URL 端口号,而不仅仅是域和路径来控制 cookie 的能力。
- 通过 Cookie 首部回送域、端口和路径过滤器(如果有的话)。
- 为实现互操作性使用的版本号。
- 在 Cookie 首部从名字中区分出附加关键字的 $ 前缀。
- 版本 1 的 Set-Cookie2 首部
- 版本 1 的 Cookie 首部
- 版本 1 的 Cookie2 首部和版本协商
11.6.8 cookie 与会话跟踪
- 图 11-5 显示了从一次 Amazon.com 访问中捕获的事务序列。
- 图 11-5a ——浏览器首次请求 Amazon.com 根页面。
- 图 11-5b——服务器将客户端重定向到一个电子商务软件的 URL 上。
- 图 11-5c——客户端对重定向的 URL 发起一个请求。
- 图 11-5d——服务器在响应上贴上两个会话 cookie,并将用户重定向到另一个URL,这样客户端就会用这些附加的 cookie 再次发出请求。这个新的 URL 是个胖 URL,也就是说有些状态嵌入到 URL 中去了。如果客户端禁止了 cookie,只要用户一直跟随着 Amazon.com 产生的胖 URL 链接,不离开网站,仍然可以实现一些基本的标识功能。
- 图 11-5e——客户端请求新的 URL,但现在会传送两个附加的 cookie。
- 图 11-5f——服务器重定向到 home.html 页面,并附加另外两个 cookie。
- 图 11-5g——客户端获取 home.html 页面并将所有四个 cookie 都发送出去。
- 图 11-5h——服务器回送内容。
11.6.9 cookie 与缓存
cookie 和缓存的规则并没有很好地建立起来。下面是处理缓存时的一些指导性规则。
- 如果无法缓存文档,要将其标示出来
- 缓存 Set-Cookie 首部时要小心
- 小心处理带有 Cookie 首部的请求
11.6.10 cookie 、安全性和隐私
cookie 是可以禁止的,而且可以通过日志分析或其他方式来实现大部分跟踪记录,所以 cookie 自身并不是很大的安全隐患。
第十二章 基本认证机制
12.1 认证
12.2 基本认证
12.1.1 HTTP 的质询 / 响应认证框架
12.1.2 认证协议与首部
HTTP 通过一组可定制的控制首部,为不同的认证协议提供了一个可扩展框架。
HTTP 定义了两个官方的认证协议:基本认证和摘要认证。
12.1.3 安全域
HTTP/1.0 401 Unauthorized
WWW-Authenticate: Basic realm="Corporate Financials"
12.2 基本认证
基本认证是最流行的 HTTP 认证协议。几乎每个主要的客户端和服务器都实现了
基本认证机制。
12.2.1 基本认证实例
12.2.2 Base-64 用户名 / 密码编码
12.2.3 代理认证
12.3 基本认证的安全缺陷
(1) 基本认证会通过网络发送用户名和密码,这些用户名和密码都是以一种很容易解码的形式表示的。实际上,密码是以明文形式传输的,任何人都可以读取并将其捕获。虽然 Base-64 编码通过隐藏用户名和密码,致使友好的用户不太可能在进行网络观测时无意中看到密码,但 Base-64 编码的用户名和密码可以很轻易地通过反向编码过程进行解码。
第13章 摘要认证
基本认证便捷灵活,但极不安全。用户名和密码都是以明文形式传送的, 也没有采取任何措施防止对报文的篡改。安全使用基本认证的唯一方式就是将其与 SSL 配合使用。
摘要认证与基本认证兼容,但却更为安全。
13.1 摘要认证的改进
- 永远不会以明文方式在网络上发送密码。
- 可以防止恶意用户捕获并重放认证的握手过程。
- 可以有选择地防止对报文内容的篡改。
- 防范其他几种常见的攻击方式。
13.1.1 用摘要保护密码
摘要认证遵循的箴言是“绝不通过网络发送密码”。客户端不会发送密码,而是会发送一个“指纹”或密码的“摘要”,这是密码的不可逆扰码。
13.1.2 单向摘要
摘要是“对信息主体的浓缩”。 6 摘要是一种单向函数,主要用于将无限的输入值转换为有限的浓缩输出值。
最重要的是如果不知道密码的话,要想正确地猜出发送给服务器的摘要将是非常困难的。同样,如果有摘要,想要判断出它是由无数输入值中的哪一个产生的,也是非常困难的。
摘要算法
MD5 安全散列算法(Secure Hash AlgorithmSHA)
13.1.3 用随机数防止重放攻击
隐藏密码并不能避免危险,因为即便不知道密码,别有用心的人也可以截获摘要,并一遍遍地重放给服务器。摘要和密码一样好用。
为防止此类重放攻击的发生,服务器可以向客户端发送一个称为随机数(nonce) 的特殊令牌,这个数会经常发生变化(可能是每毫秒,或者是每次认证都变化)。客户端在计算摘要之前要先将这个随机数令牌附加到密码上去。
13.1.4 摘要认证的握手机制
基本认证和摘要认证对比
qop quality of protection
nonce 随机数
简化的摘要认证三步握手机制
- 在第(1)步中,服务器会计算出一个随机数。在第(2)步中,服务器将这个随机数放在 WWW-Authenticate 质询报文中,与服务器所支持的算法列表一同发往客户端。
- 在第( 3 )步中,客户端选择一个算法,计算出密码和其他数据的摘要。在第( 4 )步中,将摘要放在一条 Authorization 报文中发回服务器。如果客户端要对服务器进行认证,可以发送客户端随机数。
-
在第(5)步中,服务器接收摘要、选中的算法以及支撑数据,计算出与客户端相同的摘要。然后服务器将本地生成的摘要与网络传送过来的摘要进行比较,验证其是否匹配。如果客户端反过来用客户端随机数对服务器进行质询,就会创建客户端摘要。服务器可以预先将下一个随机数计算出来,提前将其传递给客户端,这样下一次客户端就可以预先发送正确的摘要了。
13.2 摘要的计算 (todo)
摘要认证的核心就是对公共信息、保密信息和有时限的随机值这个组合的单向摘要。
13.2.1 摘要算法的输入数据
摘要是根据以下三个组件计算出来的。
- 由单向散列函数 H( d) 和摘要 KD(s,d) 组成的一对函数,其中 s 表示密码,d 表示
数据。
注 10: 但对初学者来说,可选的 RFC 2617 兼容模式以及规范中背景资料的缺乏,使其变得有些复杂。我
们会努力提供一些帮助。 - 一个包含了安全信息的数据块,包括密码,称为 A1。
- 一个包含了请求报文中非保密属性的数据块,称为 A2。
H 和 KD 处理两块数据 A1 和 A2,产生摘要。
13.2.2 算法 H(d ) 和 KD(s,d )
摘要认证支持对各种摘要算法的选择。RFC 2617 建议的两种算法为 MD5 和 MD5-sess(“sess”表示会话),如果没有指定其他算法,默认算法为 MD5。
函数 H 来计算数据的 MD5,用摘要函数 KD 来计算以冒号连接的密码和非保密数据的MD5。例如:
H() = MD5()
KD(
13.2.3 与安全性相关的数据( A1 )
被称为 A1 的数据块是密码和受保护信息的产物,它包含有用户名、密码、保护域和随机数等内容。A1 只涉及安全信息,与底层报文自身无关。A1 会与 H、KD 和A2 一同用于摘要计算。
RFC 2617 根据选择的算法定义了两种计算 A1 的方式。
- MD5
为每条请求运行单向散列函数。A1 是由冒号连接起来的用户名、域以及密码三元组。 -
MD5-sess
只在第一次 WWW-Authenticate 握手时运行一次散列函数。对用户名、域和密码进
行一次 CPU 密集型散列,并将其放在当前随机数和客户端随机数(cnonce)的前面。
13.2.4 与报文有关的数据( A2 )
数据块 A2 表示的是与报文自身有关的信息,比如 URL、请求方法和报文实体的主体部分。 A2 有助于防止方法、资源或报文被篡改。 A2 会与 H 、 KD 和 A1 一起用于摘要的计算。
RFC 2617 根据所选择的保护质量( qop ),为 A2 定义了两种策略。
- 第一种策略只包含 HTTP 请求方法和 URL。当 qop="auth" 时使用这种策略,
这是默认的情况。 -
第二种策略添加了报文实体的主体部分,以提供一定程度的报文完整性检测。
qop="auth-int" 时使用。
13.2.5 摘要算法总述
RFC 2617 定义了两种给定了 H 、 KD 、 A1 和 A2 之后,计算摘要的方式。
- 第一种方式要与老规范 RFC 2069 兼容,在没有 qop 选项的时候使用。它是用保密信息和随机报文数据的散列值来计算摘要的。
- 第二种方式是现在推荐使用的方式——这种方式包含了对随机数计算和对称认证的支持。只要 qop 为 auth 或 auth-int ,就要使用这种方式。它向摘要中添加了随机计数、 qop 和 cnonce 数据。
表 13-4 给出了得到的摘要函数定义。注意得到的摘要使用了 H、KD、A1 和 A2。
这些派生封装层很容易把人弄晕。这也是有些读者觉得 RFC 2617 难懂的原因之一。
为了简化,表 13-5 扩展了 H 和 KD 的定义,用 A1 和 A2 来表示摘要。
13.2.6 摘要认证会话
客户端响应对保护空间的 WWW-Authenticate 质询时,会启动一个此保护空间的认证会话。
在 客 户 端 收 到 另 一 条 来 自 保 护 空 间 的 任 意 一 台 服 务 器 的 WWW-Authenticate 质询之前,认证会话会一直持续。
13.2.7 预授权
在普通的认证方式中,事务结束之前,每条请求都要有一次请求 / 质询的循环。
如果客户端事先知道下一个随机数是什么,就可以取消这个请求 / 质询循环,这样客户端就可以在服务器发出请求之前,生成正确的 Authorization 首部了。
预授权方式
- 服务器预先在 Authentication-Info 成功首部中发送下一个随机数;
- 服务器允许在一小段时间内使用同一个随机数;
- 客户端和服务器使用同步的、可预测的随机数生成算法。
13.2.8 随机数的选择
RFC 2617 建议采用这个假想的随机数公式:
BASE64(time-stamp H(time-stamp ":" ETag ":" private-key))
13.2.9 对称认证
RFC 2617 扩展了摘要认证机制,允许客户端对服务器进行认证。这是通过提供客户端随机值来实现的,服务器会根据它对共享保密信息的正确了解生成正确的响应摘要。然后,服务器在 Authorization-Info 首部中将此摘要返回给客户端。
cnonce 值 和 nc 值 必 须 是 本 报 文 所 响 应 的 客 户 端 请 求 中 的 相 应 值。 如 果 指 定 了qop="auth" 或 qop="auth-int" ,就必须提供响应 auth 、 cnonce 和 nonce 计数指令。
13.3 增强保护质量
可以在三种摘要首部中提供 qop 字段: WWW-Authenticate 、 Authorization 和
Authentication-Info 。
13.3.1 报文完整性保护
如果使用了完整性保护( qop="auth-int" ),H(实体的主体部分)就是对实体主体部分,而不是报文主体部分的散列。
13.3.2 摘要认证首部
13.4 应该考虑的实际问题
13.4.1 多重质询
13.4.2 差错处理
13.4.3 保护空间
13.4.4 重写 URI
13.4.5 缓存
13.5 安全性考虑
13.5.1 首部篡改
13.5.2 重放攻击
13.5.3 多重认证机制
13.5.4 词典攻击
13.5.5 恶意代理攻击和中间人攻击
13.5.6 选择明文攻击
- 预先计算的词典攻击
- 批量暴力型攻击
13.5.7 存储密码
第14章 安全 HTTP
保护HTTP安全
HTTP 的安全版本要高效、可移植且易于管理,不但能够适应不断变化的情况而且还应该能满足社会和政府的各项要求。我们需要一种能够提供下列功能的 HTTP 安全术。
- 服务器认证(客户端知道它们是在与真正的而不是伪造的服务器通话)。
- 客户端认证(服务器知道它们是在与真正的而不是伪造的客户端通话)。
- 完整性(客户端和服务器的数据不会被修改)。
- 加密(客户端和服务器的对话是私密的,无需担心被窃听)。
- 效率(一个运行的足够快的算法,以便低端的客户端和服务器使用)。
- 普适性(基本上所有的客户端和服务器都支持这些协议)。
- 管理的可扩展性(在任何地方的任何人都可以立即进行安全通信)。
- 适应性(能够支持当前最知名的安全方法)。
- 在社会上的可行性(满足社会的政治文化需要)。
HTTPS
HTTPS 是最流行的 HTTP 安全形式。它是由网景公司首创的,所有主要的浏览器和服务器都支持此协议。
使用 HTTPS 时,所有的 HTTP 请求和响应数据在发送到网络之前,都要进行加密。
HTTPS 在 HTTP 下面提供了一个传输级的密码安全层。
14.2 数字加密
- 密码
对文本进行编码,使偷窥者无法识别的算法。 - 密钥
改变密码行为的数字化参数。 - 对称密钥加密系统
编 / 解码使用相同密钥的算法。 - 不对称密钥加密系统
编 / 解码使用不同密钥的算法。 - 公开密钥加密系统
一种能够使数百万计算机便捷地发送机密报文的系统。 - 数字签名
用来验证报文未被伪造或篡改的校验和。 - 数字证书
由一个可信的组织验证和签发的识别信息
14.2.1 密码编制的机制与技巧
14.2.2 密码
14.2.3 密码机
14.2.4 使用了密钥的密码
编码算法和编码机都可能会落入敌人的手中,所以大部分机器上都有一些号盘,可以将其设置为大量不同的值以改变密码的工作方式。即使机器被盗,没有正确的号盘设置(密钥值),解码器也无法工作。 这些密码参数被称为密钥(key)。
14.2.5 数字密码
14.3 对称密钥加密技术
很多数字加密算法都被称为对称密钥(symmetric-key)加密技术,这是因为它们在编码时使用的密钥值和解码时一样(e=d)。我们就将其统称为密钥 k。
流行的对称密钥加密算法包括:DES、Triple-DES、RC2 和 RC4。
14.3.1 密钥长度与枚举攻击
14.3.2 建立共享密钥
对称密钥加密技术的缺点之一就是发送者和接收者在互相对话之前,一定要有一个
共享的保密密钥。
14.4 公开密钥加密技术
公开密钥加密技术没有为每对主机使用单独的加密 / 解密密钥,而是使用了两个非对称密钥:一个用来对主机报文编码,另一个用来对主机报文解码。编码密钥是众所周知的。但只有主机才知道私有的解密密钥。这样,每个人都能找到某个特定主机的公开密钥,密钥的建立变得更加简单。但解码密钥是保密的,因此只有接收端才能对发送给它的报文进行解码。
14.4.1 RSA
所有公开密钥非对称加密系统所面临的共同挑战是,要确保即便有人拥有了下面所有的线索,也无法计算出保密的私有密钥:
- 公开密钥(是公有的,所有人都可以获得);
- 一小片拦截下来的密文(可通过对网络的嗅探获取);
- 一条报文及与之相关的密文(对任意一段文本运行加密器就可以得到)。
RSA 算法就是一个满足了所有这些条件的流行的公开密钥加密系统,它是在 MIT发明的,后来由 RSA 数据安全公司将其商业化。
14.4.2 混合加密系统和会话密钥
但公开密钥加密算法的计算可能会很慢。实际上它混合使用了对称和非对称策略。比如,比较常见的做法是在两节点间通过便捷的公开密钥加密技术建立起安全通信,然后再用那条安全的通道产生并发送临时的随机对称密钥,通过更快的对称加密技术对其余的数据进行加密。
14.5 数字签名
除了加 / 解密报文之外,还可以用加密系统对报文进行签名(sign),以说明是谁编写的报文,同时证明报文未被篡改过。这种技术被称为数字签名(digital signing)。
签名是加了密的校验和
数字签名是附加在报文上的特殊加密校验码。使用数字签名有以下两个好处。
- 签名可以证明是作者编写了这条报文。只有作者才会有最机密的私有密钥, 因此,只有作者才能计算出这些校验和。校验和就像来自作者的个人“签名”一样。
- 签名可以防止报文被篡改。如果有恶意攻击者在报文传输过程中对其进行了修改,校验和就不再匹配了。由于校验和只有作者保密的私有密钥才能产生,所以攻击者无法为篡改了的报文伪造出正确的校验码。
数字签名通常是用非对称公开密钥技术产生的。因为只有所有者才知道其私有密钥,所以可以将作者的私有密钥当作一种“指纹”使用。
图 14-10 显示了一个例子,说明了节点 A 是如何向节点 B 发送一条报文,并对其进行签名的。
- 节点 A 将变长报文提取为定长的摘要。
- 节点 A 对摘要应用了一个“签名”函数,这个函数会将用户的私有密钥作为参数。因为只有用户才知道私有密钥,所以正确的签名函数会说明签名者就是其所有者。在图 14-10 中,由于解码函数 D 中包含了用户的私有密钥,所以我们将其作为签名函数使用。
- 一旦计算出签名,节点 A 就将其附加在报文的末尾,并将报文和签名都发送给 B。
- 在接收端,如果节点 B 需要确定报文确实是节点 A 写的,而且没有被篡改过,节点 B 就可以对签名进行检查。节点 B 接收经私有密钥扰码的签名,并应用了
使用公开密钥的反函数。如果拆包后的摘要与节点 B 自己的摘要版本不匹配,要么就是报文在传输过程中被篡改了,要么就是发送端没有节点 A 的私有密钥(也就是说它不是节点 A)。
14.6 数字证书
本节将介绍因特网上的“ID 卡”——数字证书。数字证书(通常被称作“certs”,有点像 certs 牌薄荷糖)中包含了由某个受信任组织担保的用户或公司的相关信息。
我们每个人都有很多形式的身份证明。有些 ID,比如护照和驾照,都足以在很多场合证明某人的身份。
14.6.1 证书的主要内容
- 对象的名称(人、服务器、组织等);
- 过期时间;
- 证书发布者(由谁为证书担保);
-
来自证书发布者的数字签名。
14.6.2 X.509 v3 证书
不过好消息就是现在使用的大多数证书都以一种标准格式——X.509 v3,来存储它们信息。X.509 v3证书提供了一种标准的方式,将证书信息规范至一些可解析字段中。不同类型的证书有不同的字段值,但大部分都遵循 X.509 v3 结构。
14.6.3 用证书对服务器进行认证
通过 HTTPS 建立了一个安全 Web 事务之后,现代的浏览器都会自动获取所连接服务器的数字证书。如果服务器没有证书,安全连接就会失败。服务器证书中包含很多字段,其中包括:
- Web 站点的名称和主机名;
- Web 站点的公开密钥;
- 签名颁发机构的名称;
-
来自签名颁发机构的签名。
浏览器收到证书时会对签名颁发机构进行检查。 10 如果这个机构是个很有权威的公共签名机构,浏览器可能已经知道其公开密钥了(浏览器会预先安装很多签名颁发机构的证书)。这样,就可以像前面的 14.5 节中所讨论的那样验证签名了。图 14-12说明了如何通过其数字签名来验证证书的完整性。
14.7 HTTPS ——细节介绍
HTTPS 将 HTTP 协议与一组强大的对称、非对称和基于证书的加密技术结合在一起,使得 HTTPS 不仅很安全,而且很灵活,很容易在处于无序状态的、分散的全球互联网上进行管理。
14.7.1 HTTPS 概述
HTTPS 就 是 在 安 全 的 传 输 层 上 发 送 的 HTTP。HTTPS 没 有 将 未 加 密 的HTTP 报文发送给 TCP,并通过世界范围内的因特网进行传输(参见图 14-13a),它在将
HTTP 报文发送给 TCP 之前,先将其发送给了一个安全层,对其进行加密(参见图 14-13b)。
14.7.2 HTTPS 方案
请求一个客户端(比如 Web 浏览器)对某 Web 资源执行某事务时,它会去检查URL 的方案。
- 如果 URL 的方案为 http,客户端就会打开一条到服务器端口 80(默认情况下)的连接,并向其发送老的 HTTP 命令(参见图 14-14a)。
-
如果 URL 的方案为 https,客户端就会打开一条到服务器端口 443(默认情况下)的连接,然后与服务器“握手”,以二进制格式与服务器交换一些 SSL 安全参数,附上加密的 HTTP 命令(参见图 14-14b)。
14.7.3 建立安全传输
在未加密 HTTP 中,客户端会打开一条到 Web 服务器端口 80 的 TCP 连接,发送一条请求报文,接收一条响应报文,关闭连接。图 14-15a 对此序列进行了说明。
由于 SSL 安全层的存在,HTTPS 中这个过程会略微复杂一些。在 HTTPS 中,客户端首先打开一条到 Web 服务器端口 443(安全 HTTP 的默认端口)的连接。一旦建立了 TCP 连接,客户端和服务器就会初始化 SSL 层,对加密参数进行沟通,并交换密钥。握手完成之后, SSL 初始化就完成了,客户端就可以将请求报文发送给安全层了。在将这些报文发送给 TCP 之前,要先对其进行加密。图 14-15b 对此过程进行了说明。
14.7.4 SSL 握手
在发送已加密的 HTTP 报文之前,客户端和服务器要进行一次 SSL 握手,在这个握手过程中,它们要完成以下工作:
- 交换协议版本号;
- 选择一个两端都了解的密码;
- 对两端的身份进行认证;
- 生成临时的会话密钥,以便加密信道。
在通过网络传输任何已加密的 HTTP 数据之前,SSL 已经发送了一组握手数据来建立通信连接了。图 14-16 显示了 SSL 握手的基本思想。
14.7.5 服务器证书
SSL 支持双向认证,将服务器证书承载回客户端,再将客户端的证书回送给服务器。而现在,浏览时并不经常使用客户端证书。大部分用户甚至都没有自己的客户端证书。服务器可以要求使用客户端证书,但实际中很少出现这种情况。
安全 HTTPS 事务总是要求使用服务器证书的。
14.7.6 站点证书的有效性
- 日期检测
- 签名颁发者可信度检测
- 签名检测
- 站点身份检测
14.7.7 虚拟主机与证书
对虚拟主机(一台服务器上有多个主机名)站点上安全流量的处理有时是很棘手的。有些流行的 Web 服务器程序只支持一个证书。如果用户请求的是虚拟主机名,与证书名称并不严格匹配,浏览器就会显示警告框。
14.8 HTTPS 客户端实例
14.8.1 OpenSSL
14.8.2 简单的 HTTPS 客户端
14.8.3 执行 OpenSSL 客户端
14.9 通过代理以隧道形式传输安全流量
客户端通常会用 Web 代理服务器(参见第 6 章)代表它们来访问 Web 服务器。比如,很多公司都会在公司网络和公共因特网的安全边界上放置一个代理(参见图14-19)。代理是防火墙路由器唯一允许进行 HTTP 流量交换的设备,它可能会进行病毒检测或其他的内容控制工作。
但只要客户端开始用服务器的公开密钥对发往服务器的数据进行加密,代理就再也
不能读取 HTTP 首部了!代理不能读取 HTTP 首部,就无法知道应该将请求转向何
处了(参见图 14-20)。
为了使 HTTPS 与代理配合工作,要进行几处修改以告知代理连接到何处。一种常用的技术就是 HTTPS SSL 隧道协议。使用 HTTPS 隧道协议,客户端首先要告知代理,它想要连接的安全主机和端口。这是在开始加密之前,以明文形式告知的,所以代理可以理解这条信息。
HTTP 通过新的名为 CONNECT 的扩展方法来发送明文形式的端点信息。CONNECT 方法会告诉代理,打开一条到所期望主机和端口号的连接。这项工作完成之后,直接在客户端和服务器之间以隧道形式传输数据。 CONNECT 方法就是一条单行的文本命令,它提供了由冒号分隔的安全原始服务器的主机名和端口号。 host:port 后面跟着一个空格和 HTTP 版本字符串,再后面是 CRLF。接下来是零个或多个 HTTP 请求首部行,后面跟着一个空行。空行之后,如果建立连接的握手过程成功完成,就可以开始传输 SSL 数据了。下面是一个例子:
CONNECT home.netscape.com:443 HTTP/1.0
User-agent: Mozilla/1.1N
在请求中的空行之后,客户端会等待来自代理的响应。代理会对请求进行评估,确保它是有效的,而且用户有权请求这样一条连接。如果一切正常,代理会建立一条到目标服务器的连接。如果成功,就向客户端发送一条 200 Connection Established 响应。
HTTP/1.0 200 Connection established
Proxy-agent: Netscape-Proxy/1.1