HTTP协议
http是无状态协议,HTTP协议自身不对请求和响应之间的通信状态进行保存,就是说HTTP协议对发送过的请求或响应都不做持久化处理。
所以用户登录一家购物网站,他跳转到该网站其他页面也需要保持登录状态,所以这个时候引入了Cookie技术。
持久连接
初始版本中,每进行一次HTTP通信就要断开一次TCP连接。这样会造成无畏的TCP连接建立和断开,增加通信量的开销。所以为了解决上方问题,HTTP/1.1 想出了持久连接,只要一锻没有明确提出断开连接,则保持TCP连接状态。
管线化
持久连接使得多数请求以管线化(pipelining)方式发送成为可能。从前发送请求后需等待并收到响应,才能发送下一个请求。管线化技术出现后,不用等待响应亦可直接发送下一个请求。这样就能够做到同时并行发送多个请求,而不需要一个接一个地等待响应了。
使用 Cookie 的状态管理
无状态协议当然也有它的优点。由于不必保存状态,自然可减少服务器的 CPU及内存资源的消耗。从另一侧面来说,也正是因为HTTP 协议本身是非常简单的,所以才会被应用在各种场景里。
保留无状态协议这个特征的同时又要解决类似的矛盾问题,于是引入了 Cookie 技术。Cookie 技术通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。
Cookie 会根据从服务器端发送的响应报文内的一个叫做Set-Cookie 的首部字段信息,通知客户端保存Cookie。当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入 Cookie值后发送出去。
Cookie 相当于第一次连接后服务器端生成Cookie发送给客户端,客户端保存,然后第二次客户端请求时自动发送保存着的Cookie信息。
返回结果的HTTP状态码
状态码 | 类别 | 原因短语 |
---|---|---|
1XX | Informational(信息性状态码) | 接收的请求正在处理 |
2XX | Success(成功状态码) | 请求正常处理完毕 |
3XX | Redirection(重定向状态码) | 需要进行附加操作以完成请求 |
4XX | Client Error(客户端错误状态码) | 服务器无法处理请求 |
5XX | Server Error(服务器错误状态码) | 服务器处理请求出错 |
经常使用的大概只有14种
2XX 成功
- 200 OK
表示从客户端发来的请求在服务器端被正常处理了。
(使用 GET 方法时,对应请求资源的实体会作为响应返回;而使用 HEAD方法时,对应请求资源的实体首部不随报文主体作为响应返回(即在响应中只返回首部,不会返回实体的主体部分)。)
204 No Content
该状态码代表服务器接收的请求已成功处理,但在返回的响应报文中
不含实体的主体部分。另外,也不允许返回任何实体的主体。比如,
当从浏览器发出请求处理后,返回 204 响应,那么浏览器显示的页面
不发生更新。一般在只需要从客户端往服务器发送信息,而对客户端不需要发送新
61
信息内容的情况下使用。206 Partial Content
该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的
GET 请求。响应报文中包含由 Content-Range 指定范围的实体内容。(只请求一部分资源)
3XX重定向
3XX 响应结果表明浏览器需要执行某些特殊的处理以正确处理请
求。
- 301 Moved Permanently
永久性重定向。该状态码表示请求的资源已被分配了新的 URI,以后
应使用资源现在所指的 URI。也就是说,如果已经把资源对应的 URI
保存为书签了,这时应该按 Location 首部字段提示的 URI 重新保存。 - 302 Found
临时性重定向。该状态码表示请求的资源已被分配了新的 URI,希望
用户(本次)能使用新的 URI 访问。
和 301 Moved Permanently 状态码相似,但 302 状态码代表的资源不
是被永久移动,只是临时性质的。换句话说,已移动的资源对应的
URI 将来还有可能发生改变。比如,用户把 URI 保存成书签,但不会
像 301 状态码出现时那样去更新书签,而是仍旧保留返回 302 状态码
的页面对应的 URI。 - 303 See Other
该状态码表示由于请求对应的资源存在着另一个 URI,应使用 GET
方法定向获取请求的资源。
303 状态码和 302 Found 状态码有着相同的功能,但 303 状态码明确
表示客户端应当采用 GET 方法获取资源,这点与 302 状态码有区
别。
63
比如,当使用 POST 方法访问 CGI 程序,其执行后的处理结果是希望
客户端能以 GET 方法重定向到另一个 URI 上去时,返回 303 状态
码。虽然 302 Found 状态码也可以实现相同的功能,但这里使用 303
状态码是最理想的。 - 304 Not Modified
该状态码表示客户端发送附带条件的请求时,服务器端允许请求访问资源,但未满足条件的情况。304状态码返回时,不包含任何响应的主体部分。304 虽然被划分在 3XX类别中,但是和重定向没有关系。 - 307 Temporary Redirect
临时重定向。该状态码与 302 Found 有着相同的含义。尽管 302 标准
64
禁止 POST 变换成 GET,但实际使用时大家并不遵守。
307 会遵照浏览器标准,不会从 POST 变成 GET。但是,对于处理响
应时的行为,每种浏览器有可能出现不同的情况。
4XX客户端错误
4XX 的响应结果表明客户端是发生错误的原因所在。
- 400 Bad Request
该状态码表示请求报文中存在语法错误。当错误发生时,需修改请求的内容后再次发送请求。另外,浏览器会像 200 OK 一样对待该状态码。 - 401 Unauthorized
该状态码表示发送的请求需要有通过 HTTP 认证(BASIC 认证、
DIGEST 认证)的认证信息。另外若之前已进行过 1 次请求,则表示用 户认证失败。返回含有 401 的响应必须包含一个适用于被请求资源的WWW-Authenticate
首部用以质询(challenge)用户信息。当浏览器初次接收
到 401 响应,会弹出认证用的对话窗口。 - 403 Forbidden
该状态码表明对请求资源的访问被服务器拒绝了。服务器端没有必要
给出拒绝的详细理由,但如果想作说明的话,可以在实体的主体部分对原因进行描述,这样就能让用户看到了。
未获得文件系统的访问授权,访问权限出现某些问题(从未授权的发送源 IP 地址试图访问)等列举的情况都可能是发生 403 的原因。 - 404 Not Found
该状态码表明服务器上无法找到请求的资源。除此之外,也可以在服务器端拒绝请求且不想说明理由时使用。
5XX服务器错误
5XX 的响应结果表明服务器本身发生错误。
- 500 Internal Server Error
该状态码表明服务器端在执行请求时发生了错误。也有可能是 Web应用存在的 bug 或某些临时的故障。 - 503 Service Unavailable
该状态码表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。如果事先得知解除以上状况需要的时间,最好写入RetryAfter 首部字段再返回给客户端。
代理
代理是一种有转发功能的应用程序,它扮演了位于服务器和客户端“中间人”的角色,接收由客户端发送的请求并转发给服务器,同时也接收服务器返回的响应并转发给客户端。
使用代理服务器的理由有:利用缓存技术(稍后讲解)减少网络带宽的流量,组织内部针对特定网站的访问控制,以获取访问日志为主要目的,等等。
缓存代理:代理转发响应时,缓存代理(Caching Proxy)会预先将资源的副本(缓存)保存在代理服务器上。当代理再次接收到对相同资源的请求时,就可以不从源服务器那里获
取资源,而是将之前缓存的资源作为响应返回。
透明代理:转发请求或响应时,不对报文做任何加工的代理类型被称为透明代理(Transparent Proxy)。反之,对报文内容进行加工的代理被称为非
透明代理。
网关
网关是转发其他服务器通信数据的服务器,接收从客户端发送来的请求时,它就像自己拥有资源的源服务器一样对请求进行处理。有时客户端可能都不会察觉,自己的通信目标是一个网关。
隧道
隧道是在相隔甚远的客户端和服务器两者之间进行中转,并保持双方通信连接的应用程序。
隧道可按要求建立起一条与其他服务器的通信线路,届时使用 SSL 等加密手段进行通信。隧道的目的是确保客户端能与服务器进行安全的通信。
通过隧道的传输,可以和远距离的服务器安全通信。隧道本身是透明的,
缓存有服务器缓存,也有浏览器缓存。(注意缓存过期的问题)
HTTP首部
HTTP报文首部
其中报文包括 报文首部,空行,报文主体,如下图
HTTP请求中,HTTP 报文由方法、URI、HTTP 版本、HTTP 首部字段等部分构成。
在响应中,HTTP报文由HTTP版本、状态码(数字和原因短语)、HTTP 首部字段 3 部分构成。
HTTP首部字段
HTTP 首部字段是构成HTTP报文的要素之一。在客户端与服务器之间以 HTTP 协议进行通信的过程中,无论是请求还是响应都会使用首部字段,它能起到传递额外重要信息的作用。
使用首部字段是为了给浏览器和服务器提供报文主体大小、所使用的语言、认证信息等内容。
HTTP 首部字段根据实际用途被分为以下 4 种类型。
- 通用首部字段(General Header Fields)
请求报文和响应报文两方都会使用的首部。 - 请求首部字段(Request Header Fields)
从客户端向服务器端发送请求报文时使用的首部。补充了请求的附加内容、客户端信息、响应内容相关优先级等信息。 - 响应首部字段(Response Header Fields)
从服务器端向客户端返回响应报文时使用的首部。补充了响应的附加内容,也会要求客户端附加额外的内容信息。 - 实体首部字段(Entity Header Fields)
针对请求报文和响应报文的实体部分使用的首部。补充了资源内容更新时间等与实体有关的信息。
通用首部字段
首部字段名 | 说明 |
---|---|
Cache-Control | 控制缓存的行为 |
Connection | 逐跳首部、连接的管理 |
Date | 创建报文的日期时间 |
Pragma | 报文指令 |
Trailer | 报文末端的首部一览 |
Transfer-Encoding | 指定报文主体的传输编码方式 |
Upgrade | 升级为其他协议 |
Via | 代理服务器的相关信息 |
Warning | 错误通知 |
请求首部字段
首部字段名 | 说明 |
---|---|
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 | 对请求中 URI 的原始获取方 |
TE | 传输编码的优先级 |
User-Agent | HTTP 客户端程序的信息 |
响应首部字段
首部字段名 | 说明 |
---|---|
Accept-Ranges | 是否接受字节范围请求 |
Age | 推算资源创建经过时间 |
ETag | 资源的匹配信息 |
Location | 令客户端重定向至指定URI |
Proxy-Authenticate | 代理服务器对客户端的认证信息 |
Retry-After | 对再次发起请求的时机要求 |
Server | HTTP服务器的安装信息 |
Vary | 代理服务器缓存的管理信息 |
WWW-Authenticate | 服务器对客户端的认证信息 |
实体首部字段
首部字段名 | 说明 |
---|---|
Allow | 资源可支持的HTTP方法 |
Content-Encoding | 实体主体适用的编码方式 |
Content-Language | 实体主体的自然语言 |
Content-Length | 实体主体的大小(单位:字节) |
Content-Location | 替代对应资源的URI |
Content-MD5 | 实体主体的报文摘要 |
Content-Range | 实体主体的位置范围 |
Content-Type | 实体主体的媒体类型 |
Expires | 实体主体过期的日期时间 |
Last-Modified | 资源的最后修改日期时间 |
HTTP/1.1 版本的默认连接都是持久连接。为此,客户端会在持
久连接上连续发送请求。当服务器端想明确断开连接时,则指定Connection 首部字段的值为 Close。
HTTP/1.1 之前的 HTTP 版本的默认连接都是非持久连接。为
此,如果想在旧版本的 HTTP协议上维持持续连接,则需要指定
Connection 首部字段的值为 Keep-Alive。
为 Cookie服务的首部字段
首部字段名 | 说明 | 首部类型 |
---|---|---|
Set-Cookie | 开始状态管理所使用的Cookie信息 | 响应首部字段 |
Cookie | 服务器接收到的Cookie信息 | 请求首部字段 |
Cookie 的 HttpOnly 属性是 Cookie 的扩展功能,它使 JavaScript 脚本无法获得Cookie。其主要目的为防止跨站脚本攻击(Cross-sitescripting,XSS)对 Cookie 的信息窃取。
HTTP的安全问题
http不安全
通信使用明文(不加密),内容可能会被窃听
不验证通信方的身份,因此有可能遭遇伪装无法证明报文的完整性,所以有可能已遭篡改。
通信的加密
一种方式就是将通信加密。HTTP 协议中没有加密机制,但可以
通过和 SSL(Secure Socket Layer,安全套接层)或TLS(Transport Layer Security,安全层传输协议)的组合使用,加密 HTTP 的通信内容。用SSL建立安全通信线路之后,就可以在这条线路上进行 HTTP通信了。与 SSL 组合使用的 HTTP 被称为 HTTPS(HTTP Secure,超文本传输安全协议)或 HTTP over SSL。内容的加密
还有一种将参与通信的内容本身加密的方式。由于 HTTP 协议中没有加密机制,那么就对HTTP协议传输的内容本身加密。即把HTTP报文里所含的内容进行加密处理。在这种情况下,客户端需要对 HTTP报文进行加密处理后再发送请求.
但是内容仍有被篡改的风险。
HTTP 协议中的请求和响应不会对通信方进行确认。也就是说存在“服务器是否就是发送请求中URI真正指定的主机,返回的响应是否真的返回到实际提出请求的客户端”等类似问题。
即任何人都可发起请求,所以无法判定请求来自何方,出自谁手,即使是无意义的请求也会照单全收。无法阻止海量请求
下的 DoS 攻击。
可以通过查明对手的证书,如果使用SSL则可以。SSL不仅提供加密处理,而且还使用了一种被称为证书的手段,可用于确定方。证书是由值得信任的第三方机构颁发。
防止中间人在请求和响应传输途中,拦截并篡改内容,但是这时候作为接收方的客户端是察觉不出来的。常用的是MD5 和 SHA-1 等散列值校验的方法,以及用来确认文件的数字签名方法。提供文件下载服务的 Web 网站也会提供相应的以 PGP(Pretty Good Privacy,完美隐私)创建的数字签名及 MD5 算法生成的散列值。PGP是用来证明创建文件的数字签名,MD5 是由单向函数生成的散列值。不论使用哪一种方法,都需要操纵客户端的用户本人亲自检查验证下载的文件是否就是原来服务器上的文件。浏览器无法自动帮用户检查。
可惜的是,用这些方法也依然无法百分百保证确认结果正确。因为 PGP 和 MD5本身被改写的话,用户是没有办法意识到的。
为了有效防止这些弊端,有必要使用 HTTPS。SSL提供认证和加
密处理及摘要功能。仅靠 HTTP确保完整性是非常困难的,因此
通过和其他协议组合使用来实现这个目标。下节我们介绍HTTPS 的相关内容。
HTTP+ 加密 + 认证 + 完整性保护=HTTPS
HTTPS 并非是应用层的一种新协议。只是HTTP通信接口部分用SSL(Secure Socket Layer)和 TLS(Transport Layer Security)协议代替而已。
通常,HTTP 直接和 TCP 通信。当使用 SSL 时,则演变成先和 SSL 通信,再由SSL和TCP通信了。简言之,所谓HTTPS,其实就是身披SSL 协议这层外壳的HTTP。在采用SSL后,HTTP就拥有了HTTPS的加密、证书和完整性保护这些功能。SSL 是独立于 HTTP 的协议,所以不光是 HTTP 协议,其他运行在应
用层的 SMTP 和Telnet等协议均可配合SSL协议使用。可以说SSL是当今世界上应用最为广泛的网络安全技术。
通过数字证书加公钥及私钥来进行加密,保证客户端和服务器端安全通信。SSL
HTTPS比HTTP慢,并且因为使用了SSL,会使通信部分消耗网络资源,如CPU及内存。所以只有在包含个人信息等敏感数据时,才是用HTTPS加密通信。
HTTP认证
HTTP 使用的认证方式
HTTP/1.1 使用的认证方式如下所示。
- BASIC 认证(基本认证)
- DIGEST 认证(摘要认证)
- SSL 客户端认证
- FormBase 认证(基于表单认证)
BASIC 认证使用上不够便捷灵活,且达不到多数 Web 网站期望的安全性等级,因此它并不常用。
SSL 客户端认证采用双因素认证在多数情况下,SSL客户端认证不会仅依靠证书完成认证,一般会和基于表单认证组合形成一种双因素认证(Two-factor authentication)来使用。所谓双因素认证就是指,认证过程中不仅需要密码这一个因素,还需要申请认证者提供其他持有信息,从而作为另一个因素,与其组合使用的认证方式。
换言之,第一个认证因素的SSL客户端证书用来认证客户端计算机,另一个认证因素的密码则用来确定这是用户本人的行为。
通过双因素认证后,就可以确认是用户本人正在使用匹配正确的计算机访问服务器。
基于表单认证
认证多半为基于表单认证。由于使用上的便利性及安全性问题,HTTP协议标准提供的BASIC认证和DIGEST认证几乎不怎么使用。另外,SSL客户端认证虽然具有高度的安全等级,但因为导入及维持费用等问题,还尚未普及。
Session 管理及Cookie的应用
另外,为减轻跨站脚本攻击(XSS)造成的损失,建议事先在 Cookie内加上 httponly 属性。
如何保存表单中的密码,明文保存密码不安全,通常的安全的保存方法是,先利用给密码加盐的方式增加额外信息,再使用散列函数计算出散列值后保存。
图解HTTP 读书笔记