目录
预备知识2
数据转发2
数据缓存3
HTTP协议的请求方法3
请求方法:4
HTTP报文结构解析5
内容编码6
分块传输编码*7
多部分对象集合*8
范围请求(断点续传)8
内容协商9
HTTP状态码10
HTTP 首部字段11
通用首部字段11
请求首部字段13
响应首部字段15
实体首部字段16
为Cookie服务的首部字段16
其他首部字段*17
HTTPS协议18
HTTP认证19
HTTP的扩展协议*21
预备知识
HTTP协议属于TCP/IP协议族应用层的协议。
当前最新的HTTP协议版本是HTTP/1.1(RFC2616)
数据转发
代理:代理服务器的基本行为就是接收客户端发送的请求后转发给其他服务器,代理不改变请求URI,会直接发送给前方持有资源的目标服务器。从源服务器返回的响应经过代理服务器后再传给客户端。转发时,需要附加Via首部字段以标记出经过的主机信息:
客户端------GET HTTP/1.1------->proxy1
proxy1---------GET HTTP/1.1
Via:proxy1------>proxy2
proxy2---------GET HTTP/1.1
Via:proxy2------>源服务器
proxy2<-----HTTP/1.1 200 OK------源服务器
HTTP/1.1 200 OK------proxy2
proxy1<--------Via:proxy2
HTTP/1.1 200 OK------proxy1
客户端<--------Via:proxy1
使用代理的主要理由通常是:利用缓存技术减少网络带宽的流量,组织内部针对特定网站的访问控制,以获取访问日志为主要目的,等等。
网关:网关的工作机制和代理很相似,但是网关能使通信线路上的服务器提供非HTTP协议的服务,因此可以利用网关由HTTP请求转化为其他协议通信,与其他系统联动:
客户端-------HTTP请求------->网关-------非HTTP通信协议------->非HTTP服务器
客户端<------HTTP响应--------网关<-----非HTTP通信协议---------非HTTP服务器
隧道:隧道可按要求建立起一条与其他服务器的通信线路,然后使用SSL等加密手段进行通信,目的是确保客户端能与服务器端进行安全的通信。隧道本身不会去解析HTTP请求,而是将请求保持原样中转给之后的服务器。
数据缓存
缓存是指代理服务器或者客户端本地磁盘内保存的资源副本,利用缓存可以减少对原服务器的访问,因此也就节省了通信流量和通信时间(当代理转发从服务器返回的响应时,将会保存一份资源的副本)。
HTTP协议的请求方法
完整的URI格式:
http://user:[email protected]:80/dir/index.html?param1=value1¶m2=value2#flag
结构解析:
http:// user:pass @ www.example.com : 80 /dir/index.html? param1=value1¶m2=value2 #flag
协议 认证信息 服务器地址 端口 文件路径 查询字符串 片段标识符
持久链接(HTTP Persistent Connections、HTTP keep-alive、HTTP connection reuse)与管线化技术(pipelining):
HTTP协议的初始版本中,每进行一次HTTP通信就要断开一次TCP链接,频繁的TCP链接与断开(如请求一个有很多图片的网页)会造成无谓的流量消耗和低效的性能。
持久链接的特点是:只要任意一端没有明确地提出断开连接,则保持TCP连接状态。
在HTTP/1.1中,所有的连接默认都是持久连接,持久连接的实现需要服务器端和客户端同时支持。
持久连接使得当有多个请求时,可以以管线化方式发出请求:不用等待前一个请求的响应即可以直接发送下一个请求(实现并行请求行为)。
请求方法:
(方法名区分大小写,一定要用大写字母)
1.0和1.1都支持的方法有5个:
GET:访问已被URI标识的内容。
POST:用来传输实体的主体,与GET方法的区别在于其主要目的并不是获取响应的主体内容。
PUT:用来传输文件(写文件),因为PUT方法自身不带验证机制,因此一般的Web网站不使用该方法。
HEAD:获取报文首部,与GET方法的主要区别在于其不返回报文主体,主要用于确认URI的有效性及资源更新的日期时间等。
DELETE:删除文件,作用于PUT相反。
仅1.1支持的方法有3个:
OPTIONS:询问指定URI资源支持的方法。
TRACE:让Web服务器将之前的请求通信环回给客户端的方法,配合Max-Forwards字段,可以用来查询发送出去的请求是怎样被加工修改的。
CONNECT:要求在与代理服务器通信时建立隧道,实现用隧道协议进行TCP通信。主要使用SSL和TLS协议把通信内容加密后经网络隧道传输。
(CONNECT这个方法的作用就是把服务器作为跳板,让服务器代替用户去访问其它网页,之后把数据原原本本的返回给用户。这样用户就可以访问到一些只有服务器上才能访问到的网站了,这就是HTTP代理。CONNECT方法是需要使用TCP直接去连接的,要是使用CONNECT方法,首先要让服务器监听一个端口来接收CONNECT方法的请求。Connection验证并建立连接后会返回HTTP/1.1 200 Connection Established,否则返回HTTP/1.1 407 Unauthorized。验证通过之后,我们就可以做普通的HTTP操作了。完全可以把现在的代理服务器看作是请求连接的Internet服务器,也就是说可以像直接访问普通的服务器一样,使用GET、POST等方法来请求Internet服务器上的页面了。)
仅1.0支持,在1.1中已经废弃的方法有2个:
LINK
UNLINE
HTTP报文结构解析
HTTP报文本身其实是由CR+LF作为换行符的一个多行字符串文本,大致可以分成报文首部和报文主体两部分,这两部分由第一个出现的空行来分隔。用于请求的报文通常称为请求报文,用于响应的报文通常称为响应报文,结构如下:
请求报文 |
响应报文 |
请求报文实例 |
响应报文实例 |
|
报文首部 |
请求行 |
状态行 |
GET http://www.google.cn/ HTTP/1.1CR+LF Host: www.google.cnCR+LF Proxy-Connection: keep-aliveCR+LF Accept: text/html,appl.../webp,*/*;q=0.8CR+LF User-Agent: Mozi...36CR+LF Accept-Language: zh-CN,zh;q=0.8CR+LF Cookie: NID=67=i9vxrEuDQ7tNijPKYNau5...CR+LF |
HTTP/1.1 200 OKCR+LF Vary: Accept-EncodingCR+LF Content-Type: text/htmlCR+LF Last-Modified:...TCR+LF Date: Tue, 30 Dec 2014 08:49:48 GMTCR+LF Cache-Control: private, max-age=0CR+LF Server: sffeCR+LF |
请求首部字段 |
响应首部字段 |
|||
通用首部字段 |
通用首部字段 |
|||
实体首部字段 |
实体首部字段 |
|||
其他 |
其他 |
|||
空行 |
[CR+LF] |
[CR+LF] |
CR+LF |
CR+LF |
报文主体 |
... |
... |
<!DOCTYPE html> <html lang="zh"> <meta charset="utf-8"> <title>Google</title> <style> ... |
内容编码
HTTP可以对传输内容进行编码,内容编码后的实体由客户端接收并负责解码。通过在传输时进行编码,可以提升传输速率,但是因为编码及解码的过程需要由计算机来完成,因此会消耗更多的CPU等资源。常用的内容编码有以下几种:
gzip(GNU zip)
compress(UNIX系统的标准压缩)
deflate(zlib)
identity(不进行编码)
分块传输编码*
一般情况HTTP的Header包含Content-Length域来指明报文体的长度,有时候服务生成HTTP回应是无法确定消息大小的,比如大文件的下载,或者后台需要复杂的逻辑才能全部处理页面的请求,这时用需要实时生成消息长度,服务器一般使用chunked编码。
分块传输编码会将传输内容分成多个部分,每一部分都会用一个十六进制来标记大小,最后一部分会使用CR+LF来标记。使用分块传输编码的实体主体会由接收的客户端负责解码,恢复到编码前的实体主体。
如果一个HTTP消息(请求消息或应答消息)的Transfer-Encoding消息头的值为chunked,那么,消息体由数量未定的块组成,并以最后一个大小为0的块为结束。
每一个非空的块都以该块包含数据的字节数(字节数以十六进制表示)开始,跟随一个CRLF (回车及换行),然后是数据本身,最后块CRLF结束。在一些实现中,块大小和CRLF之间填充有白空格(0x20)。
最后一块是单行,由块大小(0),一些可选的填充白空格,以及CRLF。最后一块不再包含任何数据,但是可以发送可选的尾部,包括消息头字段。
消息最后以CRLF结尾。
例:
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
25
This is the data in the first chunk
1C
and this is the second one
3
con
8
sequence
0
HTTP 1.1引入分块传输编码提供了以下几点好处:
1.HTTP分块传输编码允许服务器为动态生成的内容维持HTTP持久链接。通常,持久链接需要服务器在开始发送消息体前发送Content-Length消息头字段,但是对于动态生成的内容来说,在内容创建完之前是不可知的。
2.分块传输编码允许服务器在最后发送消息头字段。对于那些头字段值在内容被生成之前无法知道的情形非常重要,例如消息的内容要使用散列进行签名,散列的结果通过HTTP消息头字段进行传输。没有分块传输编码时,服务器必须缓冲内容直到完成后计算头字段的值并在发送内容前发送这些头字段的值。
3.HTTP服务器有时使用压缩 (gzip或deflate)以缩短传输花费的时间。分块传输编码可以用来分隔压缩对象的多个部分。在这种情况下,块不是分别压缩的,而是整个负载进行压缩,压缩的输出使用本文描述的方案进行分块传输。在压缩的情形中,分块编码有利于一边进行压缩一边发送数据,而不是先完成压缩过程以得知压缩后数据的大小。
多部分对象集合*
发送一份报文主体内可含有多种类型的实体(通常是在图片或者文本文件等上传的时候使用)。
范围请求(断点续传)
一种网络中断可恢复机制,解决下载过程中网络中断后需要重头开始下载的问题。
例如只请求5001~10000字节内的资源:
GET /image.jpg HTTP/1.1
Host:www.test.com
Range:bytes = 5001-10000
这里用到首部字段Range,其他用法有:
从5001之后的全部字节:
Range:bytes=5001-
多重范围:从一开始到3000字节以及5000-7000字节
Range:bytes=-3001,5000-7000
针对范围请求,如果服务器端无法响应范围请求,那么便会返回状态码200 OK,和完整的实体内容。否则,便会返回状态码为206 Partial Content的响应报文:
HTTP/1.1 206 Partial Content
Date:Fri, 13 Jul 2014 04:39:17 GMT
Content-Range:bytes 5001-10000/10000
Content-Length:5000
Content-Type:image/jpeg
另外,对于多重范围的范围请求,响应会在首部字段Content-Type标明multipart/byteranges后返回响应报文。
内容协商
客户端和服务器端就响应的资源内容进行交涉,然后提供给客户端最为合适的资源。内容协商会以响应资源的语言、字符集、编码方式等作为判断的基准,这些判断基准就是请求报文中的某些首部字段:
Accept
Accept-Charset
Accept-Encoding
Accept-Language
Content-Language
HTTP状态码
状态码由3位数字和原因短语组成,如200 OK
第一位数字指定了HTTP Response的类别,主要有5种:
1,信息,接收的请求正在处理
2,成功,请求正常处理完毕
3,重定向,需要进行附加操作以完成请求
4,客户端错误,服务器无法处理请求
5,服务器端错误,服务器处理请求出错
HTTP状态码的数量在60个以上(RFC2616,4918,5842),但是常用的通常是下面这十几种:
200 OK
204 No Content # 一般用在只需要从客户端往服务器端发送信息,而服务器端不需要发送新信息的场景
206 Partial Content
301 Moved Permanently # 永久性重定向,表示请求的资源已经被分配了新的URI(具体见Location首部字段)
302 Found # 临时性重定向
303 See Other # 表示由于请求的资源存在另一个URI,应使用GET方法定向获取请求的资源
304 Not Modified # 当客户端发送附带条件的请求(If-Match、If-Modified-Since等)时,未满足条件的情况下返回。304的返回将不包含任何响应的主体部分。
307 Temporary Redirect # 临时重定向,该状态码与302有着相同的含义
400 Bad Request # 表示请求报文中存在语法错误
401 Unauthorized # 表示发送的请求需要有通过HTTP认证(BASIC或者DIGEST)的认证信息,如果浏览器是第1次接收到401响应,会弹出认证用的对话框。如果之前已进行过1次请求,则表示用户认证失败。
403 Forbidden # 访问被拒绝
404 Not Found # 服务器上没有请求的资源
500 Internal Server Error
503 Service Unavailable # 服务器正忙,一般会返回Retry-After字段
HTTP 首部字段
通用首部字段
Cache-Control:通过一系列指令来控制缓存,多个指令用逗号分隔,如:
Cache-Control:private,max-age=0,no-cache
缓存请求指令:
no-cache:强制向原服务器再次验证
no-store:不缓存请求或者响应的任何内容
max-age=[s]:响应的最大Age值(客户端告知缓存维护者,如果缓存过期不超过XX时间,就直接给我吧)
max-stale=[s]:接收已过期的响应
min-fresh=[s]:期望在指定时间内的响应仍有效
no-transform:代理不可更改媒体类型(防止压缩图片等操作)
only-if-cached:从缓存获取资源
cache-extension:新指令标记(用来扩展指令,但是其行为需要事先约定)
缓存响应指令:
public:(源服务器告诉缓存代理服务器)可向任意方提供响应的缓存
private:(源服务器告诉缓存代理服务器)仅向特定用户返回响应
no-cache:缓存前必须先确认其有效性(区别于请求指令,在响应指令中的no-cache可以带参数Cache-Control:no-cache=Location)
no-store:不缓存请求或者响应的任何内容
no-transform:代理不可更改媒体类型
must-revalidate:可缓存但必须再向源服务器进行确认(强制验证,使用该指令时将会忽略掉max-stale)
proxy-revalidate:要求中间缓存服务器对缓存的响应有效性再进行确认
max-age=[s]:响应的最大Age值(源服务器告知缓存维护者XX时间内不必再确认,可以直接支配缓存)
s-maxage=[s]:公共缓存服务器(通常指代理)响应的最大Age值,当使用该命令时,将直接忽略对Expires首部字段及max-age指令的处理
cache-extension:新指令标记
Connection:主要具备如下两个作用:
<![if !supportLists]>1.<![endif]>控制不再转发给代理的首部字段:Connection:不再转发的首部字段名(都是逐跳首部)
根据是否经过缓存代理,将HTTP首部字段分为两种,即:端到端首部(End-to-end Header)和逐跳首部(Hop-by-hop Header),逐跳首部有8个(Connection、Keep-Alive、Proxy-Authenticate、Proxy-Authorization、Trailer、TE、Transfer-Encoding、Upgrade),其他的所有首部都是端到端首部。
客户端---------GET / HTTP/1.1
Upgrade:HTTP/1.1
Connection:Upgrade---------->代理服务器------GET / HTTP/1.1----------->源服务器 #这里去掉了Upgrade
<![if !supportLists]>2.<![endif]>管理持久链接:HTTP/1.1默认使用持久链接,当想要明确断开链接时,需要使用Connection:close
HTTP/1.1之前的版本默认都是非持久链接,为此,在旧版本上想要使用持久链接,则必须将Connection设为Keep-Alive,如:
客户端---------GET / HTTP/1.1
Connection:Keep-Alive----------->服务器
Date:用来表明创建HTTP报文的日期和时间
Pragma:历史遗留字段,被Cache-Control:no-cache取代
Trailer(拖车):用来事先说明在报文主体后记录了哪些首部字段,常用于HTTP分块传输编码的场景。
Transfer-Encoding:规定了传输报文主体时采用的编码方式,仅对分块传输编码有效。
Upgrade:用于检测HTTP协议或者其他协议是否可使用更高的版本进行通信,其值可以用来指定一个完全不同的通信协议。其作用仅限于客户端和相邻服务器之间,因此还需要配合使用Connection:Upgrade。对于附有首部字段Upgrade的请求,服务器用101 Switching Protocols状态码作为相应返回。
Via:在经过代理时附加该首部字段,表名代理服务器的信息(HTTP协议版本、域名、服务器版本等):
客户端---------GET / HTTP/1.1------->proxy1
proxy1-------->GET / HTTP/1.1
Via:1.0 proxy1.com(squid/3.1)------->proxy2
proxy2-------->GET / HTTP/1.1
Via:1.0 proxy1.com(squid/3.1),1.1 proxy2.com(squid/3.2)-------->源服务器
Via首部是为了追踪传输路径,所以常和TRACE方法一起使用,如代理服务器收到由TRACE方法发送过来的请求,其中Max-Forwards:0,这时代理服务器就不能转发改请求了,代理服务器会将自身的信息附加到Via首部后,返回该请求的响应。
Warning:用来告知用户一些与缓存相关的问题的警告。定义了7种警告供参考。
请求首部字段
Accept:用来告知服务器客户端所能够处理的媒体类型及其相对优先级,可以一次指定多种媒体类型及各个类型的权重(用;进行分割):
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
类型之间用,分隔,未指定q参数,则默认为1.0,因此上例应该理解为:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
text/html(q=1.0)、application/xhtml+xml(q=1.0)、application/xml(q=0.9)、*/*(q=0.8)
Accept-Charset:告知能够处理的字符集及其相对优先级
Accept-Encoding:告知能够处理的内容编码及其相对优先级,如gzip、compress、deflate、identity(不执行压缩、默认的编码格式)
Accept-Language:告知能够处理的自然语言集及其相对优先级
Authorization:告知服务器用户代理的认证信息(证书值),通常是在收到401的返回码后,把Authorization字段加入请求中,再次请求
Expect*:告知所期望的扩展,如果服务器端不能满足期望,则会返回417 Expection Failed
From:告知服务器,用户的邮箱地址,如From:[email protected]
Host:多个虚拟主机可能运行在同一个IP上,这时候应该使用首部字段Host(域名+端口号)加以区分。若服务器未设Host,那么直接发送一个空值即可Host:。Host是HTTP/1.1规范内唯一一个必须被包含在请求内的首部字段。
If-Match:只有当If-Match的字段值和ETag值匹配一致时,服务器才会接受请求。否则返回412 Precondition Failed
ETag:实体标记,是与特定资源关联的确定值。资源更新后ETag也会随之更新。
假如用*来指定If-Match的值,服务器将会忽略ETag的值,只要资源存在就处理请求。
If-Modified-Since:如果在If-Modified-Since字段指定的日期之后资源发生了更新,服务器会接受请求,否则返回304 Not Modified
If-None-Match:与If-Match字段的作用相反,只有在If-None-Match的值与ETag值不一致的时候,可以处理该请求
If-Range:告知服务器,若指定的If-Range字段值(ETag值或者时间)和所请求的资源的ETag值或时间相一致,则做范围请求,反之则返回整个资源。
GET /index.html
If-Range:”123456”
Range:bytes=5001-10000
若If-Range字段值(ETag值或者时间)和所请求的资源的ETag值或时间相一致,则返回:
206 Partial Content
Content-Range:bytes 5001-10000/10000
Content-Length:5000
若不一致,则忽略范围请求,返回全部资源:
200 OK
ETag:”56789”
若不使用If-Range,则需要两次请求:
GET /
If-Match:”123456”
Range:5001-10000
这是服务器端返回412 Precondition Failed,于是还要再次发出请求全部资源:
GET /
If-Unmodified-Since:和If-Modified-Since的作用相反。
Max-Forwards:指定可通过的服务器的最大数目。通过TRACE或OPTIONS方法发送包含Max-Forwards首部字段的请求时,服务器在往下一个服务器转发请求之前,会将Max-Forwards的值减1后重新赋值。当服务器接收到Max-Forwards值为0的请求时,则不再进行转发,而是直接返回响应。
Proxy-Authorization:用于告知代理服务器认证所需要的信息
Range:用于范围请求的指定范围。若服务器可以处理范围请求,则返回206,若无法处理,则返回200及整个资源。
Referer:告知服务器请求的原始资源的URI,当直接在浏览器的地址栏输入URI或者出于安全性考虑时,也可以不发送该首部字段。
TE:与Accept-Encoding功能类型,但是用于传输编码。
User-Agent:将创建请求的浏览器和用户代理名称等信息传达给服务器。
响应首部字段
Accept-Ranges:告知客户端,服务器是否能处理范围请求,有两种取值:
Accept-Ranges:bytes 能
Accept-Ranges:none 不能
Age:告知客户端,源服务器在多久之前创建了响应,单位为秒。
若创建该响应的服务器是缓存服务器,Age值是指缓存后的响应再次发起认证到认证完成的时间值。代理创建响应时必须加上首部字段Age。
ETag:资源实体标识,将资源以字符串形式做唯一标识,算法取决于服务器端。(不同的资源可能对应相同的URI,这时候就要使用ETag来分辨)
ETag中有强ETag和弱ETag之分*。
Location:提供重定向的URI。
Proxy-Authenticate:把代理服务器所要求的认证信息发送给客户端。
Retry-After:告知客户端多久以后再次发出请求,主要配合503 Service Unavailable或者3XX Rediect响应一起使用,字段值可以指定为具体的日期时间,也可以是创建响应后的秒数。
Server:告知客户端当前服务器上安装的HTTP服务器程序的信息。
Vary*:用于缓存控制
WWW-Authenticate:用于HTTP访问认证,告知客户端适用于访问请求URI所指定资源的认证方案和带参数提示的质询。状态码为401的响应中,肯定带有首部字段WWW-Authenticate。
实体首部字段
Allow:用于通知客户端服务器所能接收的HTTP请求方法。当服务器接收到不支持的HTTP方法时,会以状态码405 Method Not Allowed作为响应返回,同时还会把所有能支持的HTTP方法都写入首部字段Allow中返回。
Content-Encoding:告知客户端,服务器对实体的主体部分所选用的内容编码方式。
Content-Language:告知客户端,实体主体所使用的自然语言。
Content-Length:告知客户端,实体主体部分的大小,对实体主体部分进行内容编码传输时,不能再使用Content-Length首部字段。实体主体大小的计算方法略复杂*
Content-Location:报文主体部分对应的URI,主要用于返回内容和实际请求的对象不同的场景。
Content-MD5:对报文的主体执行MD5算法后获得128位二进制数,再通过Base64编码后将结果写入Content-MD5字段值。
Content-Range:用于范围请求的返回。
Content-Type:实体主体内对象的媒体类型。
Expires:将资源失效的日期告知客户端。
当源服务器不希望缓存服务器对资源进行缓存时,可在Expires字段内写入与首部字段Date相同的时间值。
当首部字段Cache-Control有指定max-age指令时,会优先处理max-age而忽略Expires。
Last-Modified:指明资源最终修改的时间。
为Cookie服务的首部字段
Set-Cookie:响应首部字段,设置Cookie到本地
Set-Cookie字段属性:
NAME=VALUE # 键值对,可自定义
expires=DATE # 指定可发送Cookie的有效期,若未指明,则默认为浏览器关闭前为止
path=PATH # 将服务器上的文件目录作为Cookie的适用对象,若不指定,则默认为文档所在的文件目录(即限定发送Cookie的目录)
domain=域名 # 作为Cookie适用对象的域名,若不指定,则默认为创建Cookie的服务器的域名(即限定发送Cookie的域名)
Secure:仅在HTTPS通信时才会发送Cookie,例:
Set-Cookies: name=value;secure
HttpOnly:使Cookie不能被JavaScript脚本访问,即不能通过JS的document.cookie来读取附加了HttpOnly的Cookie,进而防止跨站脚本攻击。
Cookie:请求首部字段,带上本地Cookie
其他首部字段*
X-Frame-Options:用于控制网站内容在其他Web网站的Frame标签内的显示问题
X-XSS-Protection:用于控制浏览器XSS防护机制的开关
DNT:Do not track,是表示拒绝被精准广告追踪的一种方法
P3P:让Web网站上的个人隐私变成一种仅供程序可理解的形式
注:
1.HTTP首部字段可以有多个值,如:
Keep-Alive:timeout=15,max=100
2.当HTTP首部字段重复时(有多个),这种情况在规范内未定义,不同的浏览器处理逻辑不同。
3.no-store才是真正意义上的“不缓存”,no-cache应该理解为“确认缓存有效性后再进行服务”
4.应用HTTP/1.1协议的缓存服务器在遇到同时存在Expires首部字段和no-cache:max-age指令的情况时,会忽略掉Expires,而HTTP/1.0则相反。
5.Cookie不能删除,只能覆盖。
HTTPS协议
HTTP协议使用明文方式发送报文,本身不具备加密功能,不验证通信双方的身份,也无法验证报文的完整性,因此存在窃听、身份伪装和内容篡改等安全问题。
HTTPS = HTTP + 加密 + 认证 + 完整性保护,用SSL建立安全通信线路后,就可以在这条线路上进行HTTP通信,与SSL(或者TLS)组合使用的HTTP被称为HTTPS。
HTTPS的通信步骤:
[建立TCP连接]
(1)客户端------------------Handshake:ClientHello------------------->服务器 开始SSL通信,报文内容包括支持的SSL版本,加密组件列表等信息
(2)客户端<---------------Handshake:ServerHello---------------------服务器 服务器端应答,报文内容包括支持的SSL版本,加密组件列表等信息
(3)客户端<---------------Handshake:Certificate-----------------------服务器 Certificate报文中包含公开密钥证书
(4)客户端<---------------Handshake:ServerHelloDone---------------服务器 SSL握手协商结束
(5)客户端-----------------Handshake:ClientKeyExchange---------->服务器 报文内容包含一个随机密码串,且使用第(3)步中的公钥进行加密
(6)客户端-----------------ChangeCipherSpec------------------------->服务器 提示服务器,此后的报文通信会采用Pre-master secret密钥加密
(7)客户端-----------------Handshake:Finished------------------------>服务器 Finish报文,会包含连接至今全部报文整体校验值
(8)客户端<---------------ChangeCipherSpec---------------------------服务器
(9)客户端<---------------Handshake:Finished--------------------------服务器
[SSL链接建立完成,之后进行应用层协议的通信]
[应用层发送数据时会附加一种叫做MAC(Message Authentication Code)的报文摘要,能够查知报文是否遭到篡改,从而保护报文的完整性]
(10)客户端---------------Application Data(HTTP)------------------->服务器
(11)客户端<--------------Application Data(HTTP)--------------------服务器
(12)客户端----------------Alert:warning,close notify----------------->服务器 由客户端断开SSL链接
[断开TCP连接]
HTTP认证
HTTP/1.1有如下的认证方式:
BASIC认证(基本认证)
(1)客户端--------------------------------GET / HTTP/1.1
Host:test.com-------------------------------------------------------------->服务器
(2) HTTP/1.1 401 Authorization Required<----------------------------------------服务器
...
客户端<---------------------------WWW-Authenticate:Basic realm=”Input your ID and Password”
(3)客户端--------------------------------GET / HTTP/1.1
Host:test.com
Authorization:Basic ZZDJdAC23J5JaJKL=--------------------------------------->服务器
[用户ID和密码以Base64方式编码后发送]
(4) HTTP/1.1 200 OK<----------------------------------------------------------------------------服务器
...
客户端<-------------------------------Server:Apache/2.2.3(Unix)
[认证成功返回200,若认证失败则返回401]
DIGEST认证(摘要认证)
DIGEST同样使用质询/相应(challenge/response)的方式,但不会像BASIC认证那样直接发送明文密码,而是发送响应摘要及由质询码产生的计算结果。
质询/相应方式:一开始一方会先发送认证要求给另一方,接着使用从另一方那接收到的质询码计算生成响应码,接着将响应码返回给对方进行认证的方式。
SSL客户端认证
利用SSL客户端认证,可以避免因用户ID和密码被盗从而发生的第三者冒充的情况。SSL客户端认证是借由HTTPS的客户端证书完成认证的方式,凭借客户端证书认证,服务器可确认访问是否来自自己登陆的客户端。为此,需要事先将客户端证书分发给客户端,且客户端必须安装此证书。
FormBase认证(基于表单的认证)
客户端会向服务器上的Web应用程序发送登录信息,按登录信息的验证结果认证。基于表单的认证方法并不是在HTTP协议中定义的。
由于使用上的便利性及安全性问题,HTTP协议标准提供的BASIC认证和DIGEST认证几乎不怎么使用,此外SSL客户端认证虽然具有高度的安全等级,但因为导入及维持费用等问题,还尚未普及。因此,认证大多都是基于表单的认证。基于表单认证的标准和规范尚未有定论,一般会使用Cookie来管理Session,基于表单认证本身是通过服务器端的Web应用,将客户端发送过来的用户ID和密码与之前登陆过的信息做匹配来进行认证的。
HTTP的扩展协议*
SPDY:Google于2010年发布,目标在于解决HTTP的性能瓶颈,缩短Web页面的加载时间(50%)。SPDY以会话层的形式加入,控制对数据的流动,但还是采用HTTP建立通信连接,因此可照常使用HTTP的GET和POST等方法、Cookie以及HTTP报文等:
HTTP应用层
SPDY会话层
SSL表示层
TCP传输层
WebSocket:使用浏览器进行全双工通信。提供API,可供Javascript调用。
HTTP/2.0:仍在讨论中。
WebDAV:一个可对Web服务器上的内容直接进行文件复制、编辑等操作的分布式文件系统。
参考文献:
《图解HTTP》(上野 宣)