Web是建立在HTTP(HyperText Transfer Protocol,超文本传输协议)上通信的。本文是一篇HTTP协议学习笔记,补充一下HTTP协议的基础,这对于理解Ajax以及前后端交互过程绝对是非常有帮助的,本文章主要讲述Web基础和简单的HTTP协议……
Web基础
使用HTTP协议访问Web
Web页面是如何呈现的?
- 客户端通过指定的URL地址获取服务器端资源
- 服务器端使用HTTP协议传输文件资源
HTTP诞生
Web历史
- 1989.03 HTTP诞生
- 1990.11 CERN(欧洲核子研究组织)研发世界上第一台Web服务器和Web浏览器
- 1993.01 现代浏览器的祖先NCSA研发的Mosaic问世
- 1994.12 网景通信公司发布了Netscape Navigator 1.0
- 1995.xx 微软公司发布了IE 1.0和2.0
- 1995.xx Apache 0.2发布
- 1995.xx HTML2.0发布
- 2004.xx Mozilla基金会发布了Firefox浏览器
HTTP历史
- HTTP/0.9 HTTP/1.0之前的版本
- HTTP/1.0 该协议标准仍被广泛使用至服务器
- HTTP/1.1 目前主流的协议版本
网络基础TCP/IP
HTTP是TCP/IP协议族中的一个子集。
TCP/IP协议族
TCP/IP是互联网相关的各类协议族的总称,包括
- HTTP — HyperText Transfer Protocol,超文本传输协议
- FTP — File Transfer Protocil,文件传输协议
- DNS — Domain Name System,域名系统
- TCP — Transmission Control Protocol,传输控制协议
- UDP — User Data Protocol,用户数据报协议
- IP — Internet Protocol,网际协议
- PPPoE
- ICMP
- FDDI
- IEEE 802.3
TCP/IP分层管理
分层的好处是各层之间互不干涉影响,如果协议中的某个地方需要修改,只需要修改某一层即可,而不需要改变整体。只要把各层之间的接口部分规划好,每个层次内部的设计就能够自由改动了。分层如下:
- 应用层
- 传输层
- 网络层(网络互连层)
- 链路层(网络接口层、数据链路层)
应用层
决定了向用户提供服务时通信的活动。包括FTP协议、DNS协议和HTTP协议等。
传输层
上层是应用层,下层是网络层,提供处于网络连接中的两台计算机之间的数据传输。包括TCP协议和UDP协议。
网络层(网络互连层)
下层是链路层,用来处理在网络上流动的数据包。数据包是网络传输的最小数据单位。该层规定了传输路线(有路径算法),并把数据包送给对方。网络层的作用其实就是在众多的网络设备之间传输时选择一条传输路线。
链路层(网络接口层、数据链路层)
用来处理连接网络的硬件部分,包括控制操作系统、硬件的设备驱动、网络适配器(网卡)、光钎、还包括连接器等传输媒介。总而言之,硬件上的范畴都在链路层范围之内。
TCP/IP通信传输流
传输流
发送端封装
提示:发送端在层与层之间传输数据时,每经过一层时必定会被打上一个该层所属的首部信息。
接收端解封
接收端的解封流程正好是发送端的逆流程。
提示:接收端在层与层之间传输数据时,每经过一层时必定会把对应的首部消去。
DNS、TCP、IP
负责域名解析的DNS服务
DNS服务位于应用层。提供域名到IP地址之间的解析服务。计算机不仅可以赋予IP地址,也可以被赋予主机名和域名,例如域名www.baidu.com。IP地址不好记,谁能记住一大串数字,域名就比较好记,所以访问对方计算机时,可以通过域名访问而不是IP地址访问。DNS可以通过域名查找IP地址。
确保可靠的TCP协议
TCP协议位于传输层,提供可靠的字节流服务。字节流服务是将大块的数据分割以报文段为单位的数据包进行管理,可靠的传输服务是指准确可靠的把数据传输给对方。为了实现可靠传输,TCP协议采用三次握手传输策略。
负责传输的IP协议
IP协议位于网络层,作用是把各种数据包传送给对方。要传送给对方,需要两个条件,IP地址和MAC地址。
类型 说明 区别
IP 指明了节点被分配到的地址 地址可变
MAC 网络适配器(网卡)所属的固定地址 地址不可变
使用ARP协议凭借MAC地址进行通信,ARP是一种用以解析地址的协议,根据通信方的IP地址就可以反查出对应的MAC地址。
各种协议与HTTP协议的关系
第一步
第二步
URI和URL
省略。
简单的HTTP协议
本章节讲解HTTP/1.1版本的协议结构。
HTTP通信
HTTP协议和TCP/IP协议族中的其他协议都是用于客户端和服务器之间的通信。
- 客户端:请求访问文本或图像等资源的一端
- 服务器端:提供资源响应的一端
在两台计算机之间使用HTTP协议通信时,在一条通信线路上必定有一端是客户端,另一端是服务器端。
HTTP请求和响应
HTTP协议规定,请求从客户端发出,最后服务器端相应该请求并返回。注意必须先从客户端开始建立通信,服务器端在没有接收到请求之间不会发送响应。
请求报文
客户端发送一个请求,请求报文构成示例如下:
1 | //请求方法,URL |
请求报文一般由以下构成
- 请求方法,URI(粗略的可以说是URL)
- 可选的请求头首部字段
- 内容实体(请求主体)
响应报文
1 | //响应状态码 |
响应报文一般由以下构成
- 响应状态码
- 用于解释状态码的原因语句(例如OK,Not Modified等)
- 可选的响应首部字段
- 响应主体
Ajax示例
1 | function postFormData(url,data,callback){ |
HTTP是不保存状态
HTTP是一种无状态协议,HTTP协议自身不对请求和响应之间的通信状态进行保存。每当新的请求发送时,就会对应新的响应产生,协议本身并不会保留之前一切的请求和响应报文信息。当然,无状态导致了业务处理能力减弱,比如登录网站时,跳转到该站的其他页面,也需要能够继续保持登录状态,此时就需要保存用户的状态,所以为了实现这个状态功能,引入了cookie技术。有了cookie再用HTTP协议通信,就可以管理状态了。
请求URI定位资源
HTTP协议使用URI定位互联网上的资源,当客户端请求访问资源而发送请求时,URI需要将作为请求报文中的请求URI包含在内。
HTTP请求方法
请求类型 | 说明 | 作用 | 支持的HTTP协议的版本 |
---|---|---|---|
GET | 请求访问已被URI识别的资源,指定的资源经服务器解析后返回响应内容 | 获取资源 | 1.0、1.1 |
POST | 尽管GET也可以传输实体主体,但是一般还是用POST传输,POST的主要目的并不是获取响应内容 | 传输实体主体 | 1.0、1.1 |
PUT | 就像FTP协议的文件上传一样,要求在请求报文的主体中包含文件内容,没有验证机制,一般Web网站不使用 | 传输文件 | 1.0、1.1 |
HEAD | HEAD方法和GET方法类似,区别是不获取报文响应主体,用于确认URI的有效性及资源更新的日期等 获取报文首部 | 获取报文首部 | 1.0、1.1 |
DELETE | 与PUT方法相反,也没有验证机制 | 删除文件 | 1.0、1.1 |
OPTIONS | 查询针对特定请求URI指定的资源的支持的方法 | 询问支持的方法 | 1.1 |
TRACE | 通常不会用,容易引发XST(跨站追踪)攻击 | 跟踪路径 | 1.1 |
CONNECT | 实现用隧道协议进行TCP通信 要求用隧道协议连接代理 | 1.1 |
提示:HTTP/1.0还支持LINK(建立和资源之间的联系)、UNLINK(断开连接关系)方法,但是在HTTP/1.1中被废弃。此外,方法名区分大小写,注意要用大写字母。
持久连接节省通信量
HTTP初始版本中,每建立一次连接,HTTP通信就要断开一次TCP连接。随着HTTP请求的主体内容越来越大,显然这样的性能是不够的,比如获取一个网页信息时,获取HTML文档建立和断开一次TCP连接,获取图片又是一次,获取另外一张图片又是一次,增加了通信量的开销。
持久连接
针对上述问题,HTTP/1.1和部分HTTP/1.0想出了持久连接(HTTP keep-alive)的方法。只要任意一端没有明确提出断开连接,则保持TCP连接状态。持久连接旨在建立1次TCP连接后进行多次请求和响应的交互。在HTTP/1.1中所有的连接默认都是持久连接,但在HTTP/1.0内并没有标准化。
管线化
持久连接造就了管线化方式发送。以前发送请求是串行的,发送一个请求必须得到响应才能发送下一个请求,管线化技术出现后,不用等待响应亦可直接发送下一个请求。这样可以做到同时并行发送多个请求。
使用Cookie的状态管理
HTTP是无状态协议,于是引入Cookie技术。Cookie技术通过在请求和响应报文中写入Cookie信息来控制客户端状态。
没有Cookie信息状态下的客户端请求
第二次以后(存有Cookie信息状态)的请求
工作过程
第一次客户端在没有Cookie信息状体下请求连接,请求报文类似如下
1 | //请求方法,URL |
第一次服务器端接收到HTTP请求报文时,产生Set-Cookie响应首部字段,通知客户端保存Cookie
1 | //响应状态码 |
客户端形成一个Cookie文本文件存储在客户端计算机的硬件或内存中
客户端再次发送连接时,在HTTP请求报文的首部字段中添加Cookie信息并自动发送
1 | //请求方法,URL |
提问: Cookie和Session到底有什么区别呢?
HTTP报文内的HTTP信息
本章节讲解请求和响应中的报文信息。
HTTP报文
用户HTTP协议交互的信息被称为HTTP报文。客户端(请求端)的HTTP报文叫做请求报文,服务器端(响应端)的则叫做响应报文。HTTP报文大致可分为报文首部和报文主体两块。
- 报文首部: 服务器端或客户端需处理的请求或响应的内容及属性
- CR+LF (回车 + 换行)
- 报文主体:应被发送的数据
报文结构
请求报文
- 报文首部
- 请求行
- 请求首部字段
- 通用首部字段
- 实体首部字段
- 其他
- 空行(CR+LF)
- 报文主体
响应报文
- 报文首部
- 状态行
- 响应首部字段
- 通用首部字段
- 实体首部字段
- 其他
- 空行(CR+LF)
- 报文主体
说明
报文类型 | 说明 |
---|---|
请求行 | 包含请求的方法,请求URI和HTTP版本 |
状态行 | 包含表明响应结果的状态码,原因短语和HTTP版本 |
首部字段 | 包含表示请求和响应的各种条件和属性的各类首部 |
其他 | 可能包含HTTP的RFC里未定义的首部 (Cookie)等 |
提示: 请求行示例:GET/HTTP/1.1。状态行示例:HTTP/1.1 200 OK。首部字段包含:通用首部、请求首部、响应首部和实体首部。
编码提升传输速率
HTTP在传输数据时可以按照数据原貌进行传输,也可以在传输过程中通过编码提升传输速率。但是编码通过计算机来操作,需要消耗更多的CPU资源。
报文主体和实体主体的区别
- 报文: 是HTTP通信中的基本单位,由8bit字节流组成,通过HTTP通信传输。
- 实体:作为请求和响应的有效载荷数据被传输,由实体首部和实体主体组成。
通常报文的主体等于实体主体。只有编码操作时,实体主体的内容发生了变化,导致和报文主体产生了差异。
压缩传输的内容编码
HTTP协议中有一种类似ZIP压缩文件功能的内容编码功能,该功能主要应用于实体内容,并保持实体内容原样压缩。内容编码后的实体由客户端接收并负责解码。
例如请求响应头部
1 | Accept-Encoding:gzip, deflate, sdch |
常用内容编码方式:
1 | gzip(GNU zip) |
分割发送的分块传输编码
在传输大容量数据时,通过把数据分割成多块,能够让浏览器逐步显示页面。把实体主体分块的功能功称为分块传输编码。
发送多种数据的多部分对象集合
采用MIME(Multipurpose Internet Mail Extensions,多用途因特网邮件扩展)机制,允许邮件处理文本、图片、视频等多个不同类型的数据。
获取部分内容的范围请求
传输图片时突然中断,如何在恢复后从之前的中断出恢复传输,而不是重新传输图片呢?要实现恢复传输就要指定下载的实体范围。指定范围的发送的请求叫做范围请求。
例如对一份10000字节大小的资源,使用范围请求,可以只请求5001-10000字节内的资源。
- 5001-10000字节
1 | Range:bytes=5001-10000 |
- 5001字节之后的全部的
1 | Range:bytes=5001- |
- 0-3000字节、5000-7000字节的多重范围
1 | Range:bytes=-3000,5000-7000 |
内容协商返回最合适的内容
同一个Web网站有可能存在着多份相同内容的页面。比如英语版和中文版的Web页面。当浏览器默认的语言为英文或中文,访问相同的URI的Web页面时,会显示对应的英语版或中文版的Web页面。这种机制称为内容协商。
内容协商机制是指客户端和服务器端就响应的资源内容进行交涉,然后提供给客户端最为适合的资源。内容协商会以响应资源的语言、字符集、编码方式等作为判断的基准。例如
- Accept
- Accept-Charset
- Accept-Encodeing
- Accept-Language
- Content-Language
内容协商有以下3种类型
- 服务器驱动协商:服务器端进行内容协商。
- 客户端驱动协商:由客户端进行内容协商的方式。
- 透明协商:服务器驱动和客户端驱动的结合体,各自进行内容协商的一种方法。
返回结果的HTTP状体码
HTTP状态码负责表示客户端HTTP的请求的返回结果、服务器端处理是否正常、通知出现错误等工作。
状态码告知从服务器端返回的请求结果
状态码由3位数字和原因短语组成,例如200 OK,数字中的第一位指定了响应类型,后两位无分类。状态码的类别如下:
数字 类别 原因短语
1XX Information(信息性状态码) 接收的请求正在处理
2XX Success(成功状态码) 请求正常处理完毕
3XX Redirection(重定向状态码) 需要执行附加操作以完成请求
4XX Client Error(客户端错误状态码) 服务器无法处理请求
5XX Server Error(服务器错误状态码) 服务器处理请求出错
数字 | 类别 | 原因短语 |
---|---|---|
1XX | Information(信息性状态码) | 接收的请求正在处理 |
2XX | Success(成功状态码) | 请求正常处理完毕 |
3XX | Redirection(重定向状态码) | 需要执行附加操作以完成请求 |
4XX | Client Error(客户端错误状态码) | 服务器无法处理请求 |
5XX | Server Error(服务器错误状态码) | 服务器处理请求出错 |
提示:HTTP状态码数量大概有60余种,实际上经常使用的大概只有十几种。
1XX 正在处理
1XX响应结果表明请求已被接受,需要继续处理。
100 Continue
客户端应当继续发送请求。这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝。客户端应当继续发送请求的剩余部分,或者如果请求已经完成,忽略这个响应。服务器必须在请求完成后向客户端发送一个最终响应。
101 Switching Protocols
服务器已经理解了客户端的请求,并将通过Upgrade 消息头通知客户端采用不同的协议来完成这个请求。
2XX 成功
2XX响应结果表明请求被正常处理。
200 OK(常见)
表示从客户端发来的请求在服务器端被正常处理了。例如:
1 | Status Code:200 OK |
204 No Content
仍然表明请求被服务器端正常处理,但在返回的响应报文中不含实体的主体部分。
206 Partial Content
表示客户端进行了范围请求,而服务器成功执行了这部分的GET请求。响应报文中包含了由Content-Range指定范围的实体内容。
3XX 重定向
3XX响应结果表明浏览器需要执行某些特殊的处理以正确处理请求。
301 Moved Permanently
永久性重定向。如果请求的服务器资源被分配了新的URI(即修改了URI),以后就使用新的URI去指定服务器资源。比如,客户端保存了某个资源的URI作为书签,服务器端相对应资源的URI已经修改,则提醒客户端更新书签引用,从而客户端进行修改书签引用,此时就会产生301状态码。
提示:这里浏览器需要执行的特殊处理就是用新的URI去正确请求资源,如果有保存书签则更新书签。
302 Found
临时性重定向。请求的资源被分配了新的URI,希望用户(本次)能使用新的URI访问。与301状态码功能类似,但是302表示临时性变更。比如用户把对应资源的URI保存成书签,但不会像301状态码出现时那样去更新书签。
提示:这里浏览器需要执行的特殊处理就是用新的URI去正确请求资源,但是如果有书签也不更新书签。
303 See Other
该状态码表示由于请求对应的资源存在着另一个URI,应使用GET方法定向获取请求的资源。303状态码和302状态码有着相同的功能,但303明确表示客户端应采用GET方法获取资源。比如使用POST方法访问CGI程序,执行处理的结果是希望客户端能以GET方法重定向到另一个URI上去时,返回303状态码。虽然302状态码也可以实现实现相同的功能,但是这里使用303状态码更理想。
提示:很多现存的浏览器将302响应视为303响应,并使用GET方法访问在Location中规定的URI,而无视原先请求的方法。301、302、303响应状态返回时,几乎所有的浏览器都会把POST改成GET,并删除请求报文内的主体,之后请求会自动再次发送。301、302标准虽然是禁止将POST方法改变成GET的,但实际上大家都会这么做。
304 Not Modified(常见)
客户端发送附带条件的请求时,服务器端允许请求访问资源,但因发生请求未满足条件的情况后,直接返回304(服务器资源未改变,可直接使用客户端未过期的缓存),304返回时,不包含任何响应的主体部分(所以加载很快,毕竟是本地缓存嘛!)。需要注意的是,304和重定向没有关系!
附带条件的类型(任意一个就行)
- If-Modified-Since
- If-None-Match
- If-Range
- If-Unmodified-Since
示例:
1 | If-Modified-Since:Mon, 28 Sep 2015 08:00:31 GMT |
307 Temporary Redirect
临时重定向。该状态码和302 Found有着相同的含义。302标准禁止POST变换成GET,但是实际上大家并不遵守。307会遵照浏览器标准,不会从POST变成GET。
4XX 客户端错误
4XX的响应结果表明客户端是发生错误的原因所在。
400 Bad Request
400表示请求报文中存在语法错误,需修改请求内容后再次发送请求。
401 Unauthorized
401表示发送的请求需要通过HTTP认证(BASIC认真、DIGEST认证)的认证信息。当浏览器初次接收到该状态响应时,会弹出认证用的对话窗口。
403 Forbidden
403表明对请求资源的访问被服务器拒绝了,服务器可以不给出理由,如果想说明的话,可以在实体的主体部分给出详细理由说明。发生这种情况的原因可能是客户端并未获得服务器端文件系统的访问授权、访问权限出现某些问题(从未授权的的发送源IP地址进行访问)等。
404 Not Found(常见)
404表明服务器上无法找到请求的资源。当然也可以在服务器端拒绝请求且不想说明理由时使用。
5XX 服务器错误
5XX的响应结果表明服务器本身发生错误。
500 Internal Server Error (Express中常用)
500表明服务器端在执行客户端的请求时发生了错误,也可能是服务器内部出了故障。
503 Service Unavailable
503表明服务器暂时处于超负荷或正在进行停机维护,现在无法处理请求。
505 HTTP Version Not Supported
服务器不支持,或者拒绝支持在请求中使用的 HTTP 版本。这暗示着服务器不能或不愿使用与客户端相同的版本。响应中应当包含一个描述了为何版本不被支持以及服务器支持哪些协议的实体。
小结
状态码并不一定能正确表明响应状态,不少返回的状态码响应都是错误的,但是用户察觉不到。比如Web应用程序内部发生错误,状态码仍然返回200 OK。
与HTTP协作的Web服务器
一台Web服务器可搭建多个独立域名的Web网站,也可作为通信路径上的中转服务器提升传输效率。
用单台虚拟机实现多个域名
HTTP/1.1规范允许一台HTTP服务器搭建多个Web站点,因为利用了虚拟主机(虚拟服务器)的功能。客户端利用HTTP协议访问服务器时,会经常采用类似的www.hackr.jp这样的主机名和域名。域名通过DNS服务映射到IP地址(域名解析)后访问目标 网站。如果同一台服务器托管了不同的两个域名,使用DNS解析域后两者访问的IP地址会相同。
代理,网关,隧道
HTTP通信时,除了客户端和服务器意外,还有一些用于通信数据转发的应用程序,例如代理,网关和隧道,它们可以配合服务器工作。这些应用程序和服务器可以请求转发给通信线路上的下一站服务器,并且能接收那台服务器发送的响应再转发给客户端。
代理
具有转发功能,相当于客户端和服务器之间的中间人,接收到客户端发送的请求并转发给服务器,同时也可以接收服务器返回的响应并转发给客户端。网关
转发其他服务器的通信数据的服务器,接收从客户端发送来的请求时,可以从其他服务器上获取资源然后就像自己拥有资源的源服务器一样对请求进行处理。客户端可能都不知道自己的通信目标是一个网关。隧道
服务器和客户端如果非常远,可以使用隧道进行中转,并保持双方通信连接的应用程序。
代理
HTTP通信过程中,可级联多台代理服务器,转发时,需要附加Via首部字段以标记出经过的代理服务器信息。同时,通过设置组织内部的代理服务器可做到针对特定URI访问的控制。代理服务器的作用:
- 利用缓存技术减少网络带宽的流量
- 组织内部针对特定网站的访问控制
- 获取访问日志
代理有多种使用方法,一种是否使用缓存,一种是否会修改报文。
缓存代理
代理转发响应时,缓存代理会预先将资源的副本缓存在代理服务器上,如果接收到相同资源的请求时,可以不从源服务器那里获取资源,将之前缓存的资源作为响应返回。透明代理
转发请求或响应时,不对报文做任何加工的代理类型被称为透明代理,反之被称为非透明代理。
网关
网关的工作机制和代理有点相似,但是网关能使通信线路上的服务器提供非HTTP协议服务。利用网关提高通信的安全性,可以在客户端和网关的通信线路上加密以确保连接的安全。
隧道
通过隧道的传输,可以和远距离的服务器安全通信,隧道本身是透明的,客户端不用在意隧道的存在。
保存资源的缓存
缓存有两种,一种是保存在代理服务器上的资源副本,一种是在客户端本地磁盘内保存的资源副本。利用缓存可以节省通信流量和通信时间。缓存服务器是代理服务器的一种,归类为缓存代理类,当代理转发从源服务器返回的额响应时,代理服务器会保存一份资源的副本,如果下一次请求同样的资源,则直接由缓存服务器返回给客户端,而不是再次去请求源服务器。因此客户端可就近从缓存服务器上获取资源,而源服务器也不必多次处理相同的请求了。
缓存的有效期
缓存的数据是有有效期的,不然源服务器更新了资源以后,仍然从缓存服务器获取数据则请求的将是’旧’资源了。所以会因为客户端的要求、缓存的有效期等因素,向源服务器确认资源的有效性。若判断了缓存失效,缓存服务器将从源服务器上获取’新’资源。
客户端的缓存
缓存当然不仅仅可以缓存在代理服务器(缓存服务器)上,还可以存在客户端浏览器中。以IE程序为例,把客户端缓存称为临时网络文件。浏览器缓存有效,就不必再向服务器请求相同的资源了,可以直接从本地磁盘内读取。和缓存服务器相同的一点是,当判断缓存过期,会向源服务器确认资源的有效性,若判断浏览器缓存失效,浏览器会再次请求新资源。
HTTP首部
HTTP协议的请求和响应报文中必定包含HTTP首部,只是平时用户在使用时感受不到它。
HTTP报文首部
HTTP请求报文
访问hackr请求报文示例:
1 | Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 |
HTTP响应报文
访问hackr响应报文示例:
1 | Accept-Ranges:bytes |
HTTP首部字段
HTTP首部字段传递重要信息
使用首部字段是为了给浏览器和服务器提供报文主体大小、所使用的语言、认证信息等内容。比如浏览器可以告诉服务器只能解释中文,而服务器可以告诉浏览器多少时间后再过来访问。
HTTP首部字段结构
首部字段由首部字段名和首部字段值构成,例如Content-Type用来表示报文主体的对象类型
1 | Content-Type:text/html |
首部字段名 首部字段值
Content-Type text/html
首部字段名 | 首部字段值 |
---|---|
Content-Type | text/html |
首部字段值对应的单个HTTP首部字段可以有多个值,例如
1 | Accept-Encoding:gzip, deflate, sdch |
提示:如果首部字段重复,则根据浏览器内部处理逻辑不通,结果可能并不一致,有些浏览器首先处理第一次出现的首部字段,有些则会优先处理最后出现的首部字段。
HTTP首部字段类型
首部字段类型 | 说明 |
---|---|
通用首部字段 | 请求报文和响应报文都会使用的首部 |
请求首部字段 | 请求报文会使用的首部 |
响应首部字段 | 响应报文会使用的首部 |
实体首部字段 | 针对请求报文和响应报文的实体部分使用的首部 |
HTTP/1.1首部字段预览
- 通用首部字段
Cache-Control: 控制缓存的行为
Connection:逐级首部、连接管理
Date: 创建报文的日期时间
Pragma:报文指令
Trailer:报文末端的首部一览
Transfer-Encoding:指定报文主体的传输编码方式
Upgrade:升级为其他协议
Via:代理服务器的相关信息
Warning:错误通知
- 请求首部字段
Accept:用户代理可处理的媒体类型
Accept-Charset:优先的字符集
Accept-Encoding:优先的内容编码
Accept-Language: 优先的语言
Authorization:Web认真信息
Host :请求资源所在服务器
If-Modified-Since :比较资源的更新时间
If-Range:资源未更新时发送实体Byte的范围请求
Range:实体的字节范围请求
User-Agent:HTTP客户端程序的信息
- 响应首部字段
Accept-Ranges :是否接受字节范围请求
Age:推算资源创建经过时间
ETag :资源的匹配信息
Location:令客户端重定向至指定的URI
Server:HTTP服务器的安装信息
Vary :代理服务器缓存的管理信息
- 实体首部字段
Allow:资源可支持的HTTP方法
Content-Encoding:实体主体的自然语言
Content-Length:实体主体的大小(单位:字节)
Content-Location :替代对应资源的URI
Content-Range:实体主体的位置范围
Content-Type:实体主体的媒体类型
Expires :实体主体过期的日期时间
Last-Modified:资源最后修改的日期时间
非HTTP/1.1首部字段
比如Cookie、Set-Cookie等。
End-to-end首部和Hop-by-hop首部
端到端首部
会转发给请求(响应)对应的最终接收目标,且必须保存在由缓存生成的响应中,另外规定它必须被转发。逐跳首部
只对单次转发有效,会因通过缓存或代理而不再转发,HTTP/1.1和之后的版本如果要使用Hop-by-hop首部需提供Connection首部字段。
逐跳首部字段有以下8种,除了这些以外的都是端到端首部
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- Trailer
- TE
- Transfer-Encoding
- Upgrade
HTTP/1.1通用首部字段
请求报文和响应报文双方都会使用的首部。
Cache-Control
使用此首部可以操作缓存机制。参数可选,使用,分隔,示例如下
1 | Cache-Control:max-age=0,no-cache |
缓存请求指令
指令参数 | 参数 | 说明 |
---|---|---|
no-cache | 无 | 强制向源服务器再次验证 |
no-store | 无 | 不缓存请求(响应)的任何内容 |
max-age=[秒] | 必需 | 响应的最大Age值 |
no-transform | 无 | 代理不可更改媒体类型 |
only-if-cached | 无 | 从缓存获取资源 |
缓存响应指令
指令 参数 说明
public 无 可向任意方提供响应的缓存
private 可省略 仅向特定用户返回省略
no-cache 可省略 缓存前必须先确认其有效性
no-store 无 不缓存请求(响应)的任何内容
max-age=[秒] 必需 响应的最大Age值
s-maxage=[秒] 必需 公共缓存服务器响应的最大Age值
no-transform 无 代理不可更改媒体类型
指令参数 | 参数 | 说明 |
---|---|---|
public | 无 | 可向任意方提供响应的缓存 |
private | 可省略 | 仅向特定用户返回省略 |
no-cache | 可省略 | 缓存前必须先确认其有效性 |
no-store | 无 | 不缓存请求(响应)的任何内容 |
max-age=[秒] | 必需 | 响应的最大Age值 |
max-age=[秒] | 必需 | 响应的最大Age值 |
s-maxage=[秒] | 必需 | 公共缓存服务器响应的最大Age值 |
no-transform | 无 | 代理不可更改媒体类型 |
能否缓存
public
1 | Cache-Control:public |
明确表明其他用户也可利用缓存。
private
1 | Cache-Control:private |
缓存服务器会对特定用户提供资源缓存的服务,对于其他用户发送过来的请求代理服务器不会返回缓存。
no-cache
1 | Cache-Control:no-cache |
使用no-cache目的是防止从缓存中返回过期的资源。客户端发送请求如果包含该指令则表示客户端不会接收缓存过的响应。缓存服务器必须把客户端的请求转发给源服务器(强制向源服务器验证)。如果源服务器返回的响应包含该指令,那么缓存服务器不能对资源进行缓存,源服务器以后也不会对缓存服务器请求中提出的资源有效性进行确认,禁止对响应资源进行缓存操作。
提示:无参数的响应(源服务器发送的首部字段)首部字段可以在客户端使用缓存,不能在缓存服务器使用缓存。
1 | Cache-Control:no-cache=Location |
如果对no-cache指定具体参数值,那么客户端在接收到这个被指定参数值得首部字段对应的响应报文后,就不能使用缓存,当然无参数的首部字段可以在客户端使用缓存。
提示:只能在响应指令中指定该指令的参数值。
控制可执行缓存的对象的指令
no-store
1 | Cache-Control:no-store |
暗示请求或响应中包含机密信息,规定缓存不能在本地存储请求或响应的任一部分。
提示: no-store是真正的不进行缓存,而no-cache代表不缓存过期的资源。
缓存期限和认证
max-age
1 | Cache-Control:max-age=6000(单位是秒) |
客户端发送请求中如果判定缓存资源的缓存时间数值比指定时间的数值更小,那么客户端就接收缓存的资源,如果指定max-age为0,那么缓存服务器通常需要将请求转发给源服务器。而服务器返回的响应中包含max-age指令时,缓存服务器将不对资源的有效性再做确认,max-age数值代表资源保存为缓存的最长时间。
提示:HTTP/1.1缓存服务器遇到同时存在Expires首部字段的情况时,会优先处理max-age指令,而HTTP/1.0恰好相反。
s-maxage
1 | Cache-Control:s-maxage=6000(单位:秒) |
s-maxage指令的功能和max-age相同。不同点在于s-maxage指令只适用于提供多位用户使用的公共缓存服务器(代理服务器)。对于同一用户重复返回响应的服务器没有任何作用。
提示:使用s-maxage会忽略Expires和max-age。
min-fresh
1 | Cache-Control:min-fresh=60(单位:秒) |
该指令要求缓存服务器返回至少还未过指定时间的缓存资源。如果指定60s,在这60s以内如果有超过有效期限的资源都无法作为响应返回。
must-revalidate
1 | Cache-Control:must-revalidate |
代理会向源服务器再次验证即将返回的响应缓存目前是否仍然有效。若代理无法向源服务器再次获取有效资源的话,缓存必须给客户端一条504状态码。
no-transform
1 | Cache-Control:no-transform |
无论请求还是响应,缓存不能改变主体的媒体类型。可防止缓存(代理)压缩图片等类似操作。
Connection
- 控制不再转发给代理的首部字段
- 管理持久连接
控制不再转发给代理的首部字段
1 | Upgrade:HTTP/1.1 |
在客户端发送请求和服务器返回响应内,使用Connection首部字段可控制不再转发给代理的首部字段。
管理持久连接
1 | Connection:Keep-Alive |
HTTP/1.1默认都是持久连接的。以上是客户端请求响应时的持久连接首部信息。
1 | Connection:close |
服务器想明确断开连接,则指定该首部字段的值为close。
Date
1 | Date:Thu, 23 Jun 2016 06:19:55 GMT |
该首部字段表明创建HTTP报文的日期和时间。
Pragma
1 | Pragma:no-cache |
该首部字段是HTTP/1.1之前的版本遗留字段,为了向低版本的HTTP协议兼容,一般需要加上该字段,作用和Cache-Control:no-cache一样,虽然属于通用首部字段,但是只用在客户端发送的请求中。客户端会要求所有的中间服务器不返回缓存的资源。为了兼容,一般会把两个首部字段都加上。
Transfer-Encoding
1 | Transfer-Encoding:chunked |
规定了传输报文主体时采用的编码方式。HTTP/1.1的传输编码方式对分块传输编码有效。
Upgrade
1 | Upgrade:HTTP/1.1 |
用于检测HTTP协议及其他协议是否可使用更高版本进行通信,参数也可以指定一个完全不同的通信协议。
1 | Upgrade:TLS/1.0 |
必须这样捆绑使用,因为Upgrade首部字段产生的作用仅限于客户端和邻接服务器之间。
Via
追踪客户端和服务器之间的请求和响应报文的传输路径。报文经过代理和网关时会先在首部字段Via中附加该服务器的信息,然后在进行转发。
Warning
1 | Warning: [警告码] [警告的主机:端口号] "[警告内容]" ([日期时间]) |
提示:警告码和含义可以查阅相关资料。
HTTP/1.1请求首部字段
Accept
1 | Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 |
Accept首部字段可通知服务器用户代理能够处理的媒体类型及媒体类型的相对优先级。使用type/subtype形式,一次可以指定多种媒体类型。以下是媒体类型举例:
媒体类型 | 说明 |
---|---|
文本文件 | text/html,text/plain,text/css, application/xhtml+xml,application/xml… |
图片文件 | image/jpeg,image/gif,image/webp,image/png… |
视频文件 | video/mpeg,video/quicktime… |
应用程序使用的二进制文件 | application/octet-stream,application/zip… |
使用q=可以表示要显示的媒体类型的权重值,用;分割,范围是0-1(可精确到小数点后三位),且1是最大值,默认权重值为1。客户端向服务器请求媒体数据时,当服务器可以提供多种媒体类型时,首先返回权重值最高的媒体类型。
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),采用Lempel-Ziv算法(LZ77)及32位循环冗余校验(CRC) |
compress | 由UNIX文件压缩程序compress生成的编码格式,采用Lmepel-Ziv-Welch算法(LZW) |
deflate | 组成使用zlib格式及由deflate压缩算法生成的编码格式 |
identity | 不执行压缩或不会变化的默认编码格式 |
提示:使用最多的当然是gzip编码格式,其次还有其他的一些编码格式例如sdch。
Accept-Language
1 | Accept-Language:zh-CN,zh;q=0.8 |
告知服务器客户端能够处理的自然语言集(英文、中文等),可一次指定多种自然语言集。
Authorization
告知服务器客户端(用户代理)的认证信息(证书值)。
Expect
1 | Expect:100-continue |
客户端使用首部字段Expect来告知服务器期望出现的某种特定行为。但是好像HTTP/1.1规范只指定了100-continue。
Host
1 | Host:hackr.jp |
首部字段告诉服务器请求资源所处的互联网主机名和端口号。Host首部字段在HTTP/1.1中是唯一一个必须被包含在请求内的首部字段。
if-Match
1 | If-Match:12345 |
条件请求之一(If-xxx),服务器接收到附带条件的请求后,只有判断指定条件为真时,才会执行请求。只有当If-Match的字段值跟ETag值匹配一致时,服务器才会接受请求。
if-Modified-Since
1 | If-Modified-Since:Tue, 08 Jan 2013 08:53:29 GMT |
告知服务器,若if-Modified-Since的字段值早于资源的更新时间,则希望能处理该请求。如果在指定if-Modified-Since字段值的日期时间之后,资源都没有更新,则返回状态码304 Not Modify。
if-Modified-Since的时间 < 资源更新的时间 = 返回新资源
否则资源未更新过则返回状态码304 Not Modify。
if-Modified-Since用于确认代理和客户端拥有的本地资源的有效性,获取资源的更新日期时间,可通过首部字段Last-Modified来确定。
if-None-Match
与If-Match作用相反,不匹配ETag值时才会接受请求。
if-Range
1 | If-Range:"123445" |
告知服务器若指定的If-Range字段值(Etag值或者时间)和请求资源的Etag值或时间相一致时,则作范围请求处理。反之,返回全体资源。
if-Unmodified-Since
与if-Modified-Since作用相反。
Max-Forwards
以十进制整数形式指定可经过的服务器最大数目。当值为0时,则不再进行转发,必须直接返回响应。此值在跟踪通信过程时非常有用,比如要途径多个转发服务器时,转发失败,客户端就很难得到服务器返回的响应了,而且我们也不知道是哪个代理服务器出了问题,此时可以设定Max-Forwards值来初定了解传输路径的通信情况。需要注意的是该值没经过一个代理服务器自减1,如果值为0则不再转发,必须强制返回响应。
Proxy-Authorization
接收到从代理服务器发来的认证质询时,客户端会发送包含首部字段Proxy-Authorization的请求,告知服务器认证所需要的信息。
Range
1 | Range:bytes=5001-10000 |
范围请求时告知服务器资源的指定范围。如果请求成功,则返回206状态码,无法处理该范围请求时,返回200及全部资源。
TE
1 | TE:gzip,deflate;q=0.5 |
告知服务器客户端能够处理响应的传输编码方式及相对优先级。和Accept-Encoding的功能很像,但是用于传输编码。
User-Agent
1 | User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36 |
告诉服务器创建请求的浏览器和用户代理的名称,中间可能会被添加上代理服务器的名称。
HTTP/1.1响应首部字段
Accept-Ranges
1 | Accept-Ranges:bytes |
告诉客户端是否能处理范围请求,none指明不能处理,bytes指明处理成功。
Age
1 | Age:600(单位:秒) |
告诉客户端源服务器多久前创建了响应。
ETag
1 | ETag:"4324hkh23h4h34fdhs4732hfadsjk" |
ETag告知客户端实体标识,它是将资源以字符串形式做唯一性标识的方式,服务器会为每份资源分配对应的ETag值,资源更新时,ETag值也会更新。若在下载过程中出现连接中断、再连接的情况,都会按照ETag值来指定资源。
提示:ETag值有强弱之分。
Location
1 | Location:http://www.ziyi2.cn/index.html |
可以将响应接收方引导至某个与请求URI位置不同的资源。该字段会配合3xx:Redirection的响应,提供重定向URI。即服务器端如果将需要访问的资源转移到一个新的URI后,客户端发起请求,服务器就会返回一个带Location字段的响应通知客户端重定向到新的URI,通常客户端在接收到这个字段时都会强制性的尝试对已提示的重定向资源进行访问。
Proxy-Authorizaticate
注意与请求响应的首部字段名Proxy-Authorization是配合起来使用的,该字段是会把代理服务器要求的认证信息发送给客户端。
Retry-After
告诉客户端多久之后再次发送请求。可以具体指定日期或者创建响应后的秒数。
Server
1 | Server:Apache/2.2.17(Unix) |
告知客户端当前服务器上安装的HTTP服务器应用程序的信息。可能还会标出服务器的版本号和安装时启动的可选项。
Vary
1 | Vary:Accept-Encoding,User-Agent |
对缓存进行控制,源服务器向代理服务器传达关于本地缓存使用方法的命令就是Vary字段,当客户端发起请求时,只对Vary指定的请求首部相同的HTTP请求(HTTP请求报文中的对应首部字段名和字段值和Vary中指定的一样),才会返回缓存。如果不同,那么将从源服务器重新获取资源。
WWW-Authenticate
用于HTTP访问认证。会告诉客户端适用于访问请求URI所指定资源的认证方案(Basic或Digest)。
HTTP/1.1实体首部字段
请求实体和响应实体都会含有一些信息,所以在请求报文和响应报文要加入相关实体部分信息的首部字段。
Allow
1 | Allow:GET,HEAD |
用于通知客户端能够支持Request URL指定资源的所有Request Method方法(HTTP请求方法)。如果服务器接收都不支持的HTTP方法,会以状态码405 Method Not Allowed作为响应返回,还会把所有支持的方法写入Allow首部字段返回。
Content-Encoding
1 | Content-Encoding:gzip |
告知服务器对实体的主体部分选用的内容编码方式。
Content-Language
告知客户端实体主体使用的自然语言。
Content-Length
实体主体部分的大小(单位是Byte)。
Content-Location
报文主体返回资源相对应的URI。
Content-MD5
服务器端返回资源时,会对报文主体进行MD5算法,接着进行Base64编码,客户端会对接收到的报文主体进行同样的算法,从而得出一个128bit的二进制数,如果该数一样,则表明报文主体传输过程完整。其实起到的是一个校验的作用。
Content-Range
1 | Content-Range:bytes 5001-10000/10000 |
针对范围请求,返回资源时告诉客户端作为响应返回的实体的哪个部分符合范围请求。
Content-Type
1 | Content-Type:text/css; charset=utf-8 |
说明实体主体对象的媒体类型。
Expires
将资源失效的日期告知客户端。缓存服务器接收到含有该字段的响应后,会缓存来应答请求,在Expires指定的时间之前,响应的副本会一直被保存,超过指定的时间后,缓存服务器在请求发送过来时,会转向源服务器请求资源。
Last-Modified
指明资源最终修改的时间,指定的是Request URL指定资源被修改的时间。
为Cookie服务的首部字段
Cookie的工作机制是用户识别及状态管理。调用Cookie时可校验有效期、发送方的域、路径、协议等信息,所以正规发布的Cookie内的数据不会因来自其他Web站点和攻击者的攻击而泄露。
首部字段名 | 说明 | 首部类型 |
---|---|---|
Set-Cookie | 开始状态管理所使用的cookie信息 | 响应首部字段 |
Cookie | 从服务器接收到的Cookie | 请求首部字段 |
Set-Cookie
1 | Set-Cookie:BDSVRTM=123; path=/ |
当服务器准备开始管理客户端的状态时,会事先告知各种信息。
属性 | 说明 |
---|---|
NAME=VALUE | 赋予Cookie的名称和其值(必需项) |
expires = DATE | Cookie的有效期(若不明确指定则默认为浏览器关闭前为止) |
path = PATH | 将服务器上的文件目录作为Cookie的适用对象(不指定则默认在文档所在的文件目录) |
domain = 域名 | 作为Cookie适用对象的域名(若不指定则默认为创建Cookie的服务器域名) |
Secure | 仅在HTTPS安全通信时才会发送Cookie |
HttpOnly | 加以限制,使Cookie不能被JavaScript脚本访问 |
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属性
用于限制Web页面仅在HTTPS安全连接时,才可以发送Cookie。使用方法如下:
1 | Set-Cookie:BDSVRTM=123; path=/; secure |
HttpOnly属性
该属性是Cookie的扩展功能,使JavaScript脚本无法获得Cookie。主要目的是为了防止跨站脚本攻击(Cross-site scripting,XSS)对Cookie信息的获取。指定方法如下:
1 | Set-Cookie:BDSVRTM=123; path=/; HttpOnly |
通过以上设置,通常从Web页面还可以对Cookie进行读取操作,但是使用JavaScript的document.cookie就无法读取附加该属性后的Cookie内容了。所以在无法再XSS中利用JavaScript劫持Cookie。
Cookie
告知服务器,客户端想要获得HTTP状体管理支持时,就会在请求中包含从服务器接收到的Cookie,接收到多个,就可以以多个的形式发送。
其他首部字段
HTTP首部字段是可以自行扩展的,所以在Web服务器和浏览器的应用上会出现各种非标准的首部字段。
X-Frame-Options
1 | X-Frame-Options:DENY |
属于响应首部,控制网站内容在其他Web网站的Frame标签内的显示问题。目的是为了防止点击劫持攻击。
- DENY:拒绝
- SAMEORIGIN:仅在同源域名下的页面匹配时许可(比如http://hackr.jp/sameple.html页面为SAMEORIGIN时,那么hackr.jp上所有页面的frame都被允许可加载该页面,而example.com等其他域名就不被允许了)。
并不是所有浏览器都支持该首部,当然主流的浏览器一般都能支持。
提示:一般在HTTP协议中,给非标准参数加上前缀X-,用来区别标准参数。
X-XSS-Protection
属于响应首部,这对跨站脚本攻击(XSS)的一种策略,用于控制浏览器XSS防护机制的开关。
- 0:将XSS过滤设置成无效状态
- 1:将XSS过滤设置成有效状态
DNT
1 | DNT:1 |
HTTP请求首部,意思是Do Not Track,拒绝个人信息被收集,表示拒绝被精准广告追踪的一种方法。
- 0:同意被追踪
- 1:拒绝被追踪
确保Web安全的HTTPS
在HTTP协议中有可能存在信息窃听或身份伪装等安全问题,使用HTTPS通信机制可以有效的防止这类问题。
HTTP缺点
- 通信使用明文(不加密),内容可能被窃取
- 不验证通信身份,容易遭遇伪装
- 无法证明报文的完整性,可能遭篡改
通信使用明文
HTTP报文使用明文(通信的请求和响应的内容未经过加密处理)方式发送。
TCP/IP是可能被窃听的网络
互联网上的任何角落都存在通信内容被窃听的风险,包括客户端、代理服务器、互联网和源服务器等。只要收集来互联网上流动的数据帧就可以了,这些工作可以通过抓包(Packet Capture)嗅探器(Sniffer)工具,例如抓包工具( Wireshark)。例如查看发送的请求和返回的响应,以及响应报文的全部内容等一系列事情都可以做到。
加密处理防止被窃听
- 通信的加密
HTTP协议本身没有加密机制,可以使用SSL(Secure Socket Layer,安全套接层)或TLS(Transport Layer Security,安全传输层协议)的组合使用,加密通信内容。用SSL建立安全通信线路之后,就可以在这条线路上进行HTTP通信了。使用SSL组合使用HTTP被称为HTTPS(HTTP Secure,超文本传输安全协议)或HTTP over SSL。 - 内容的加密
对传输的HTTP报文中的内容主体加密(不对报文首部加密)。为了做到内容加密,客户端和服务器需要同时具备加密和解密机制。但是不同于SSL或TLS将整个通信线路加密处理,内容仍然有被篡改的风险。不验证通信身份
HTTP协议中的请求和响应不会对通信方进行确认,不验证请求的客户端和返回响应的服务器。
任何人都可以发起请求
HTTP协议的实现本身非常简单,不论是谁发送过来的请求都会返回响应(当然前提是发送端的IP地址和端口号没有被Web服务器设定限制访问的前提下)。无法确认请求的那台服务器是否是伪装的Web服务器。
无法确认返回响应的客户端是否是伪装的客户端。
- 无法判定请求是谁。
- 无意义的请求也会照单全收,无法阻止海量请求下的Dos攻击(Denial Of Service,拒绝服务攻击)。
- 查明对手的证书
使用SSL则可以确定通信方。SSL不仅提供加密处理,还使用了证书手段,用于确定方。证书由第三方机构颁发,难以伪造,通过使用证书,客户端可以完成个人身份的确认,也可用于对Web网站的认证环节。
无法证明报文的完整性
即无法确认报文信息的准确度。
- 接收到的内容可能有误
无法确认发出的请求和接收到的响应是前后一致的,比如从服务器下载文件,在响应过程的中途可能遭到篡改,而使得下载的文件是篡改后的文件而不是原来需要的源服务器上的文件。这种在传输中途遭到攻击拦截并篡改内容的攻击称为中间人攻击(Man-in-the-Middle attack,MITM)。 - 防止篡改
有确定报文完整性的方法,例如使用MD5和SHA-1等散列值校验方法,以及提供文件下载服务的Web网站也会提供相应的PGP(Pretty Good Privacy,完美隐私)创建数字签名和MD5算法生成散列值,但是算法本身也有可能被篡改,用户是意识不到的,所以HTTP本身很难确保报文的完整性,有必要使用HTTPS,毕竟SSL提供认证和加密处理功能。
HTTPS
HTTP + 加密 + 认证 + 完整性保护
HTTP协议中使用未经过机密的明文,比如在Web页面中输入信用卡号,如果通信线路遭到窃听,那么信用卡号就暴露了!另外,HTTP协议无法确认通信方,无论是客户端还是服务器,所以需要使用在HTTP基础上添加加密及认证机制的HTTP(HTTP Secure, HTTPS)。使用HTTPS通信时,使用的是https://而不是http://(通常会在登录页面和购物车结算页面使用)。
HTTP 披上外壳SSL
HTTPS并非是应用层的一种新协议。只是HTTP通信接口部分用SSL和TLS协议代替而已。应用层HTTP通常一般直接和传输层的TCP通信,而HTTPS则是使应用层HTTP先和SSL通信,再由SSL和TCP通信。
HTTP
- 应用层 HTTP
- 传输层 TCP
- 网络层 IP
HTTPS
- 应用层HTTP
- 表示层SSL
- 传输层TCP
- 网络层IP
SSL是独立于HTTP的协议,与其他协议也可以配合使用的,可以说SSL是目前使用最广泛的网络安全技术。
加密技术
SSL采用一种公开密钥加密的加密处理方式。加密和解密都会用到密钥,没有密钥就无法对密码解密。
- 共享秘钥加密
加密和解密同用一个秘钥的方法称为共享秘钥加密或者对称秘钥加密。这种方法需要把秘钥发送给对方,比如客户端需要和服务器通信加密,需要把秘钥发送给服务器(毕竟用同一个秘钥嘛),转发秘钥时如果通信被监听秘钥就会被攻击者获取。 - 使用两把秘钥的公开秘钥加密
公开秘钥加密使用一对非对称的秘钥,一把叫做私有秘钥,一把叫做公开秘钥。私有秘钥不能让任何人知道,公开秘钥任意人都可以获取。发送密文的一方使用对方发送过来的公开秘钥进行加密处理(比如要实现加密,服务器先给客户端发送一个公开秘钥),对方接收到加密后的信息时,再使用自己的配套公开秘钥的私密秘钥进行解密(客户端发送了按照公开秘钥加密的报文,服务器使用对应的私有秘钥进行解密工作)。这种方式根本不需要担心公开秘钥被窃听。同时根据公开秘钥和密文对信息原文进行解密也是异常困难的。 - HTTPS采用混合加密机制
HTTPS采用共享秘钥加密和公开秘钥加密混合使用加密机制。因为后者与前者相比,处理速度要慢,所以在能够实现安全通信的情况下,使用共享秘钥加密。 - 使用公开秘钥加密的机制传送稍后需要用到的共享秘钥加密的秘钥。
- 建立通信后交换报文阶段则使用共享秘钥加密方式。
证明公开秘钥正确性的证书
怎么证明公开秘钥本身又是货真价实的公开秘钥呢?例如如何证明客户端接收到的公开秘钥是对应的服务器发行的公开秘钥?因为公开秘钥也容易被攻击者劫持啊。此时可以使用数字证书认证机构(CA,Certificate Authority)和其相关机关颁发的公开秘钥证书。需要注意的是数字证书认证机构是需要客户端和服务器双方都可信任的第三方机构。
提示:注意区分机构的私有秘钥和服务器的公有秘钥,机构的私有秘钥用来加密数字签名,服务器的公有秘钥最终是为了进行和客户端通信时可以使用公开秘钥加密的加密机制。公钥证书包含服务器提交的公开秘钥和数字证书机构认证的数字签名。
验证服务器公开秘钥的正确性:客户端拿到公钥证书后,使用数字证书认证机构的公开秘钥对数字签名进行解密,验证服务器公开秘钥的真实性,如果正确,则使用服务器提出的公开秘钥对报文进行加密传输。
解密过程:接收到客户端发送的加密报文后,使用服务器对应的私有秘钥进行解密操作。
秘钥类型 | 作用 |
---|---|
服务器公开秘钥 | 通信时加密用 |
服务器私有秘钥 | 通信时解密用 |
认证机关的私有秘钥 | 向服务器提交的公开秘钥部署数字签名 |
认证机关的公开秘钥 | 在客户端验证服务器公开秘钥的正确性 |
提示:认证机关的公开秘钥必须安全的转交给客户端,通常多数浏览器开发商发布版本时,事先在内部植入常用认证机关的公开秘钥。
可证明组织真实性的EV SSL证书
EV SSL证书严格规定了对运营组织是否真实的确认方针,可以防止用户被钓鱼攻击。用以确认客户端的客户端证书
HTTPS还可以使用客户端证书。以客户端证书进行客户端认证。例如银行的网上银行就是采用客户端证书,在登录网银时不仅要求用户确认输入的ID和密码,还会要求用户的客户端证书,以确认用户是否从特定的终端访问网银。认证机构信誉第一
如果认证结构被黑,那么SSL的可信度?- 由自认证机构颁发的证书称为自签名证书
该证书容易被认定是伪造的证书,没有什么大用?HTTPS的安全通信机制
HTTPS通信步骤
提示: master Secret是报文校验码的秘钥。
- SSL和TLS
HTTPS使用SSL和TLS这两个协议。SSL最初由浏览器开发商网景通信公司率先倡导的。TLS则是以SSL为原型(SSL3.0为基准)开发的协议。有时统一称该协议为SSL。 - SSL速度慢
HTTPS使用SSL时,处理速度会变慢。因为需要做服务器、客户端双方的加密和解密处理,会消耗CPU和内存等硬件资源。和HTTP通信相比,SSL通信又在TCP通信之上建立了一层握手通信,消耗网络资源,时间上延长了。和HTTP通信相比,网络负载可能会慢2-100倍。解决办法是可以使用SSL加速器(专用服务器)硬件来提高SSL的计算速度。小结
为什么不一直使用HTTPS通信呢?一方面是某些信息并不敏感,例如网页的呈现等,可以使用HTTP通信,并且加载速度比HTTPS也要快(网络负载更少),只有在获取和提交某些敏感信息时才需要使用HTTPS通信。
确认访问用户的认证
某些Web页面只想让特定的人浏览,比如网上银行,或者干脆仅本人可见。为达到这个目的,必不可少的就是认证功能。
何为认证
计算机本身无法判断坐在显示器前的使用者的身份。为了知道谁在访问服务器,需要让客户端自报家门,通常核对客户端身份的信息有如下几种:
- 密码
- 动态令牌
- 数字证书
- 生物认证
- IC卡等
HTTP的认证方式
HTTP/1.1使用的认证方式如下所示:
- BASIC认证(基本认证)
- DIGEST认证(摘要认证)
- SSL客户端认证
- FormBase认证(基于表单认证)
BASIC认证
BASIC认证(基本认证)是从HTTP/1.0就定义的认证方式。Web服务器与通信客户端之间进行的认证方式。
提示:401 Authorization Required首部字段值还包含了认证方式BASIC。
BASIC认证虽然采用Base64编码方式,但仍然是不加密处理的,在HTTP等非加密通信的线路上进行BASIC认证的过程中,很容易被人窃听。所以BASIC认证的安全性还不够高。
DIGEST认证
为了弥补BASIC认证存在的弱点,从HTTP/1.1起就有了DIGEST认证。该认证同样使用质询/响应的方式,但不会像BASIC认证那样直接发送明文密码。
SSL客户端认证
从使用用户ID和密码的认证方式方面来讲,只要二者内容正确一致,就可认证是本人操作,但是如果用户的账号和密码被窃取,很有可能是第三者冒充。利用SSL客户端认证则可以避免这个情况。SSL客户端认证是由HTTPS的客户端证书完成认证的方式。凭借客户端证书认证,服务器可确认访问是否来自已登录的客户端。
客户端认证步骤
步骤一:接收认证资源的请求,服务器发送Certificate Request报文,要求客户端提供客户端证书。
步骤二:用户选择将发送的客户端证书后,客户端会把客户端证书信息以Client Certificate报文方式发送给服务器。
步骤三:服务器验证客户端证书验证通过后可领取证书内客户端的公开秘钥,然后开始HTTPS加密通信。
提示: 为了进行SSL客户端认证,需要事先安装客户端证书。
SSL客户端认证采用双因素认证
SSL客户端认证不仅依靠证书完成认证,还会和基于表单认证组合形成一种双因素认证。第一个认证因素是SSL客户端证书用来认证客户端计算机,第二个认证因素的密码来确定是用户本人的行为。
基于表单认证
基于表单的认证方法并不是HTTP协议中定义的。客户端会向服务器上的Web应用程序发送登录信息,按登录信息的验证结果认证。
认证多半是基于表单认证
BASIC认证和DIGEST认证因为使用上的便利性和安全性几乎不怎么使用,基于SSL的客户端认证虽然具有高度的安全性,但因为导入及维持费用等问题,还尚未普及。对于Web网站认证功能,能够满足其安全使用级别的标准规范并不存在,所以只好使用由Web应用程序各自实现基于表单的认证方式。
Session管理及Cookie应用
基于表单认证的标准规范尚未有定论,一般会使用Cookie来管理Session。基于表单认证本身是通过服务器端的Web应用,将客户端发送过来的用户ID和密码与之前登陆过的信息做匹配来进行认证的。但是HTTP是无状态协议,之前已认证成功的用户状态无法通过协议层面保存下来,HTTP无法实现状态管理。因此即使当该用户的下一次继续访问,也无法区分他与其他用户。于是我们会使用Cookie来管理Session,以弥补HTTP协议中不存在的状态管理功能。
步骤一:客户端把自己的ID和密码等登录信息收入报文的实体部分,通常是以POST方法把请求发送给服务器。这时会使用HTTPS通信来进行HTML表单画面的显示和用户输入数据的发送。
步骤二:服务器会发放用以识别用户的Session ID。通过验证客户端发送过来的账号和密码,然后把用户的认证状态与Session ID绑定后记录在服务器端。向客户端返回响应时,会在首部字段Set-Cookie内写入Session ID(如Set-Cookie:PHPSESSID=028a8c…)。可以把Session ID想象成用以区分不同用户的等位号,然而如果Session ID被第三方盗走,对方就可以伪装成你的身份进行操作了,因此必须防止Session ID被盗,或被猜出。一般Session ID使用难以推测的字符串,且服务器端也需要进行有效期的管理,保证其安全性。另外为减轻跨站脚本攻击(XSS),建议事先给Cookie加上httponly属性。
步骤三:客户端接收到从服务器端发来的Session ID后,会将其作为Cookie保存在本地。下次向服务器发送请求时,浏览器会自动发送Cookie,所以Session ID随之发送到服务器,服务器可通过验证接收到的Session ID识别用户和其认证状态。
不仅表单认证的登录信息及认证过程没有标准化的方案,服务器端应如何保存用户提交的密码等登录信息也没有被标准化。通常一种安全的保存密码方法是先利用密码加盐(salt)的方式增加额外信息,在使用散列值(hash)函数计算出散列值后保存,而不要直接保存明文密码,容易导致密码泄露。
提示:加盐就是由服务器随机生成一个字符串,长度足够长,并且是真正随机生成的,把它和密码字符串相连接(前后都可以)生成散列值。当两个用户使用了同一个密码时,由于随机生成的salt值不同,对应的散列值也将是不同的,很大程度上减少了密码特征,攻击者也很难破解。
基于HTTP的功能追加协议
随着互联网的快速发展,HTTP协议在功能上已经捉襟见肘,本章讲解基于HTTP新增功能的协议。
SPDY
Google在2010年发布了SPDY(取自SPeeDY,发音同speedy),目标旨在解决HTTP性能瓶颈,缩短Web页面的加载时间(50%)。
HTTP瓶颈
一条连接只能发送一个请求
请求只能从客户端开始,客户端不可以接收除响应以外的指令
请求/响应首部未经过压缩就发送,首部信息越多延迟越大
发送冗长的首部,每次发送相同的首部造成浪费颇多
可任意选择数据压缩格式,非强制压缩发送
Ajax解决方法
Ajax(Asynchronous JavaScript and XML,异步JavaScript与XML技术)是一种有效利用JavaScript和DOM(Document Object Model,文档对象模型)的操作,以达到局部Web页面替换加载的异步通信手段。由于更新一部分页面而不是全部页面,响应中传输的数据量会少很多,优点显而易见。Ajax的核心技术是名为XMLHttpRequest的API,通过JavaScript脚本语言的调用就能和服务器进行HTTP通信,从而能从加载完毕的Web页面发起请求,只更新局部页面。
利用Ajax实时的从服务器获取内容,有可能导致大量的请求产生,另外Ajax仍未解决HTTP协议本身存在的问题。
Comet解决方法
一旦服务器有内容更新,Comet不会让请求等待,而是直接给客户端返回响应。通过延迟应答,模拟实现服务器端向客户端推送的功能。 通常服务器端接收到请求,在处理完毕后会立即返回响应,但为了实现推送功能,Comet会先将响应置于挂起状态,当服务器端有内容更新时,再返回该响应。因此一旦服务器端有更新,就可以立即反馈给客户端。内容上虽然能够做到实时更新,但是为了保留响应,一次连接的持续时间也变长了,为了维持连接会消耗更多的资源,另外Comet仍未解决HTTP协议本身存在的问题。
SPDY目标
陆续出现的Ajax和Comet等提高易用性的技术,使HTTP得到了部分改善,但HTTP协议本身的限制仍然未解决,SPDY协议正在HTTP协议层面进行持续开发,为了消除HTTP瓶颈。
SPDY设计与功能
- 应用层HTTP
- 会话层SPDY
- 表示层SSL
- 传输层TCP
SPDY在HTTPS的基础上新增了会话层,仍然采用HTTP建立通信连接,可照常使用HTTP的GET和POST等方法,Cookie以及HTTP报文等。使用SPDY后,HTTP协议额外获得功能:
- 多路复用流
通过单一的TCP连接,可以无限制处理多个HTTP请求,所有请求的处理都在一条TCP连接上完成,TCP处理效率得到提高。 - 赋予请求优先级
可以为请求分配优先级顺序,在发送多个请求时,解决因宽带而导致响应变慢的问题。 - 压缩HTTP首部
- 推送功能
Comet技术支持服务器主动向客户端推送数据。 - 服务器提示功能
SPDY性能
SPDY只是将单个域名(IP地址)的通信多路复用,在Web网站使用多个域名下的资源,改善效果就会受到限制,但是SPDY的确是一种可有效消除HTTP瓶颈的技术。
使用浏览器进行全双工通信的WebSocket
通信使用HTTP协议,无法彻底解决HTTP瓶颈问题,WebSocket网络技术正是解决问题而实现的一套新协议及API。当时筹划的WebSocket将作为HTML5的一部分,而现在它却逐渐变成了独立的协议标准。
WebSocket的设计与功能
WebSocket是Web浏览器与Web服务器之间全双工通信标准。其中WebSocket协议由IETF定位标准,WebSocket API由W3C定位标准。WebSocket目前主要是为了解决Ajax和Comet里XMLHttpRequest附带的缺陷所引起的问题。
WebSocket协议
一旦Web服务器与客户端之间建立了WebSocket协议的通信连接,之后所有的通信都依靠这个专用协议进行。可以在通信过程中互相发送JSON、XML、HTML或图片等任意格式的数据。由于是建立在HTTP基础上的协议,因此连接的发起方仍然是客户端,而一旦确立WebSocket通信连接,不论服务器和客户端,任意一方都可以直接向对方发送报文。 而不是传统的HTTP协议必须是客户端发起请求,服务器给出请求的响应。
- 推送功能
支持由服务器向客户端推送数据的推送功能。这样服务器可以直接发送数据而不是等待客户端的请求。 - 减少通信量
只要建立起WebSocket连接,就希望一直保持连接状态。和HTTP协议相比,不但每次连接时的总开销减少,而且由于WebSocket的首部信息很小,通信量也相对减少。 - 握手
为了实现WebSocket通信,在HTTP连接建立后,只需要完成一次握手的步骤。
握手请求
为了实现WebSocket通信,需要用到HTTP的Upgrade首部字段,告知服务器通信协议发生改变,已达到握手的目的。
1 | Request Method:GET |
Sec-WebSocket-Key字段记录着握手过程中必不可少的键值。Sec-WebSocket-Protocol字段记录使用的子协议。
握手响应
对于之前的请求,返回状态码101 Switching Protocols的响应。
1 | Status Code:101 Switching Protocols |
Sec-WebSocket-Accept字段值是由握手请求中的Sec-WebSocket-Key字段值生成的。如果成功握手确立WebSocket连接之后,通信时不再使用HTTP的数据帧,而采用WebSocket独立的数据帧。
WebSocket是全双工通信,因此服务器端不必等待请求,可直接发送数据,从而实现服务器端推送功能。
提示:当HTTP握手动作结束时,浏览器和服务器之间就形成了一个快速通道,当然从WebSocket名字也可以理解这个快速通道类似于Socket连接,客户端和服务器端就可以通过TCP连接直接交换数据了,快速通道连接一直持续到客户端或服务器端的某一方主动的关闭连接。所以WebSocket本质上是一个基于TCP的协议。
WebSocket API
JavaScript可调用WebSocket API内提供的WebSocket程序接口,以实现WebSocket协议下的全双工通信。
1 | var webSocket = new WebSocket(url,[subProtocol]); //创建一个WebSocket对象 |
提示:url是指定连接的URL,subProtocol是可选的子协议。
WebSocket事件
事件 | 事件处理程序 | 说明 |
---|---|---|
open | webSocket.onopen | 连接建立时触发 |
message | webSocket.onmessage | 客户端接收服务端数据时触发 |
error | webSocket.onerror | 通信发生错误时触发 |
close | webSocket.onclose | 连接关闭时触发 |
WebSocket方法
send():使用连接发送数据
close(): 关闭连接
WebSocket属性
属性 | 说明 |
---|---|
Socket.readyState | 表示连接状态 |
Socket.bufferedAmount | 只读属性,表明已经被send()放入发送等待列表但是还没有发出的UTF-8文本字节数 |
客户端使用示例:
1 | function WebSocketExample(data){ |
HTTP/2.0
回顾一下HTTP的发展历史:
- HTTP/0.9
已经过时,只接受GET一种请求方法,没有在通讯中指定版本号,且不支持请求头,由于该版本不支持POST方法,所以客户端无法向服务器传递太多信息。 - HTTP/1.0
在通讯中指定版本号的HTTP协议,至今仍被广泛使用,特别是在代理服务器中。 - HTTP/1.1
与HTTP/1.0相比,主要区别在于 - 缓存处理
- 带宽优化及网络连接的使用
- 错误通知的管理
- 消息在网络中发送
- 互联网地址维护
- 安全性及完整性
目前主流的HTTP/1.1标准,在SPDY和WebSocket出现以后,很难断言仍是适用于当下的Web的协议。于是负责互联网技术标准的IETF(Internet Engineering Task Force,互联网工程任务组)创立了httpbis工作组,目标是推进下一代HTTP(HTTP/2.0)。
HTTP/2.0特点
- SPDY
- HTTP Speed + Mobility
- Network-Friendly HTTP Upgrade
HTTP Speed + Mobility由微软公司起草,用于改善提高移动端通信时通信速度和性能的标准。建立与Google公司提出的SPDY与WebSocket的基础之上。
HTTP/2.0 的7项技术及讨论
压缩 SPDY、Friendly
多路复用 SPDY
TLS义务化 Speed + Mobility
协商 Speed + Mobility、 Friendly
客户端拉拽和服务器推送 Speed + Mobility
流量控制 SPDY
WebSocket Speed + Mobility
Web服务器管理文件的WebDAV
WebDAV(Web-based Distributed Authoring and Versioning,基于万维网的分布式创作和版本控制)是一个可对Web服务器上的内容直接进行文件复制、编辑等操作的分布式文件系统。除了创建、删除文件等基本功能,它还具备文件创建者管理、文件编辑过程中禁止其他用户内容覆盖的加锁功能,以及对文件内容修改的版本控制功能。
使用HTTP/1.1的PUT方法和DELETE方法就可以对Web服务器上的文件进行创建和删除操作。但是出于安全性考虑一般是不使用的。
WebDAV新增的方法及状态码
方法
FROPFIND:获取属性
PROPPATCHL:修改属性
MKCOL:创建集合
…
状体码
102 Processing:可正常处理请求,但目前是处理中状态
207 Multi-Status:存在多种状态
423 Locked:资源已被加锁
…