个人整理。主要来自《图解HTTP》以及百度百科、csdn博客等。
HTTP基础知识
1 HTTP简介
1.1 什么是HTTP
当用户在网页浏览器(Web browser)的地址栏输入URL时,Web浏览器需要从Web服务器端获取文件资源等信息,从而显示出Web页面。为了完成从客户端到服务器端的通信,Web使用了HTTP(HyperText Transfer Protocol,超文本传输协议)。
1.2 HTTP的特点
HTTP具有以下特点:
- HTTP属于应用层协议,在传输层使用TCP,在网络层使用IP。此外,在通信过程中还会用到DNS(解析域名)与ARP(获取MAC地址)等。
- 使用HTTP时,必定是一端担任客户端,另一端担任服务器端。即便实际情况下可能两端都既是服务器端,也是客户端,但仅就一条通信线路而言,客户端与服务器端是确定的。HTTP能够明确区分哪边是客户端,哪边是服务器端。
- HTTP请求必然是由客户端发出,而服务器端回复响应。服务器端在没有接收到请求之前不会发送响应。
- HTTP一种无状态协议,即HTTP自身不对请求和响应之间的通信状态进行保存。每当有新的请求发送时,就会有对应的新响应产生。
- 如果服务器端需要管理客户端状态,可以使用Cookie技术。Cookie技术通过在请求和响应报文中写入Cookie信息来控制客户端的状态。
- HTTP的初始版本中,每进行一次HTTP通信就要连接和断开一次TCP连接。后引入了持久连接(Persistent Connections,也称为HTTP keep-alive或HTTP connection reuse)方法,能实现只要任意一端没有明确提出断开连接,则保持TCP连接状态。
1.3 URI与URL
URI全称为Uniform Resource Identifier,统一资源标识符,作用是标识某一互联网资源。
URL全称为Uniform Resource Locator,统一资源定位符,用于表示资源的地点。
URI与URL的联系是它们都能够唯一地确定一个资源,区别是URL是通过资源的地点来确定资源的,而URI除了通过资源的地点,还能用其他字符串句法格式来确定资源。因此,可以说URL是URI的子集。
绝对URI格式:协议方案名://[登录信息@]服务器地址:端口号/带层次的文件路径[?查询字符串][#片段标识符]
1.4 HTTP请求报文
HTTP请求报文由请求方法、请求URI、协议版本、可选的请求首部字段和内容实体构成。其中请求方法、请求URI、协议版本组成请求行。
1.5 HTTP响应报文
HTTP响应报文由协议版本、状态码、原因短语、可选的响应首部字段以及内容实体构成。其中协议版本、状态码、原因短语组成响应行。
2 HTTP/1.1中可用的方法
方法用于将客户端的请求告知服务器端。
2.1 GET:获取资源
GET方法用来请求访问已被URI识别的资源,指定的资源经服务器端解析后返回响应内容。
2.2 POST:传输实体主体
POST方法用来传输实体的主体。
2.3 PUT:传输文件
PUT方法用来传输文件。需要在请求报文的主体中包含文件内容,然后保存到请求URI指定的位置。
2.4 HEAD:获取报文首部
HEAD方法与GET方法一样,只是不返回报文主体部分。一般用于确认URI的有效性及资源更新的日期时间等。
2.5 DELETE:删除文件
DELETE方法用于按请求URI删除指定的资源。
2.6 OPTIONS:询问支持的方法
OPTIONS用法用来查询针对请求URI指定的资源(也可用*代替,表示任意资源)支持的方法。
2.7 TRACE:追踪路径
TRACE方法用于让Web服务器将之前的请求通信返回给客户端。发送请求时,需要在Max-Forwards首部字段中填入数值,每经过一个服务器端就将该数字减一。当数值归零时停止传输,并由最后接收到请求的服务器端返回状态码200 OK的响应。
2.8 CONNECT:要求用隧道协议连接代理
CONNECT方法要求在于代理服务器通信时建立隧道,实现用隧道协议进行TCP通信。
3 HTTP状态码
状态码用于当客户端向服务器端发出请求时,描述请求的处理结果。
3.1 1XX:正在处理
1XX的响应结果表示接收的请求正在处理。
3.2 2XX:成功
2XX的响应结果表明请求被正常处理了。
3.2.1 200 OK
表示从客户端发来的请求被服务器正常处理了,在响应报文内会根据请求类型返回相应的信息,如GET方法返回对应资源实体,HEAD方法返回首部等。
3.2.2 204 No Content
表示服务器成功处理了请求,但返回的报文中不含实体的主体部分。一般在只需要从客户端向服务器发送信息,而不需要向客户端发送信息时使用。
3.2.3 206 Partial Content
表示客户端进行了范围请求,而服务器成功执行了这部分的GET请求。响应报文中包含由Content-Range指定范围的实体内容。
3.3 3XX重定向
3XX的响应结果表示浏览器应当执行一些特殊处理以正确访问资源。
3.3.1 301 Moved Permanently
永久性重定向,表示请求的资源已被分配了新的URI,以后应使用资源现在所指的URI。
3.3.2 302 Found
临时性重定向,表示请求的资源已被分配的新的URI,希望用户本次能使用新的URI访问。
3.3.3 303 See Other
表示对应当前请求的响应可以在另一个 URI 上被找到,而且客户端应当采用 GET 的方式访问那个资源。
3.3.4 304 Not Modified
如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码。
3.3.5 307 Temporary Redirect
请求的资源临时从不同的URI 响应请求。新的临时性的URI 应当在响应的 Location 域中返回。除非这是一个HEAD 请求,否则响应的实体中应当包含指向新的URI 的超链接及简短说明。因为部分浏览器不能识别307响应,因此需要添加上述必要信息以便用户能够理解并向新的 URI 发出访问请求。
3.4 4XX客户端错误
4XX的响应结果表明客户端的请求发生错误。
3.4.1 400 Bad Request
该状态码表示请求报文中存在语法错误。当错误发生时,需修改请求的内容后再次发送请求。
3.4.2 401 Unauthorized
当前请求需要用户验证。该响应必须包含一个适用于被请求资源的 WWW-Authenticate 信息头用以询问用户信息。如果当前请求已经包含了 Authorization 证书,那么401响应代表着服务器验证已经拒绝了那些证书。如果401响应包含了与前一个响应相同的身份验证询问,且浏览器已经至少尝试了一次验证,那么浏览器应当向用户展示响应中包含的实体信息,因为这个实体信息中可能包含了相关诊断信息。
3.4.3 403 Forbidden
表示对请求资源的访问被服务器拒绝了。
3.4.4 404 Not Found
表示服务器上无法找到请求的资源,也可以用于拒绝请求而不想说明理由。
3.5 5XX
5XX的响应结果表明服务器本身发生错误。
3.5.1 500 Internal Server Error
表明服务器端在执行请求时发生了错误,也可能是Web应用存在bug或某些临时故障。
3.5.2 503 Service Unavailable
表明服务器暂时处于超负载或正在停机维护,无法处理请求。
4 HTTP首部
4.1 HTTP首部简介
HTTP首部字段是构成HTTP报文的要素之一。在客户端与服务器使用HTTP通信的过程中,无论是请求还是相应都会用到首部字段,它能起到传递额外信息的作用。
HTTP首部字段是由首部字段名和字段值构成的,中间用冒号隔开(首部字段名:字段值)。例:Content-Type:text/html。对应单个首部字段的字段值可以有多个。
根据实际用途,HTTP首部字段被分为以下4种类型:
- 通用首部字段(General Header Fields):请求报文和响应报文都会使用的首部。
- 请求首部字段(Request Header Fields):从客户端向服务器端发送请求报文时使用的首部,补充请求的附加内容、客户端信息等。
- 响应首部字段(Response Header Fields):从服务器端向客户端返回响应报文时使用的首部,补充了响应的附加内容以及要求客户端附加的额外内容信息等。
- 实体首部字段(Entity Header Fields):针对请求报文和响应报文的实体部分使用的首部,补充了资源内容更新时间等与实体相关的信息。
还有一种分类将首部字段根据缓存代理和非缓存代理的行为,分为一下两种:
- 端到端首部:会转发给请求/响应的最终接收目标,且规定它必须被转发。
- 逐跳首部:只对单次转发有效,会因通过缓存或代理而不再转发。
属于逐跳首部字段的有(其他都属于端到端首部):
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- Trailer
- TE
- Transfer-Encoding
- Upgrade
在HTTP/1.1及以后的协议中,如要使用逐跳首部字段,需要同时提供Connection首部字段。
4.2 HTTP/1.1通用首部字段
4.2.1 Cache-Control
用于操作缓存的工作机制。可用字段值如下:
(1)Cache-Control:public
表明其他用户也可使用缓存。
(2)Cache-Control:private
当指定private指令后,响应只以特定的用户作为对象。缓存服务器会对该特定用户提供资源缓存服务,对于其他用户则不提供。
(3)Cache-Control:no-cache
该指令的目的是防止从缓存中返回过期资源。
客户端请求如果包含no-cache,则表示客户端将不会接收缓存过的响应,缓存服务器必须把客户端请求转发给原服务器。
服务器请求如果包含no-cache,那么缓存服务器不能对资源进行缓存,源服务器以后也将不再对缓存服务器提出的资源有效性进行确认,且禁止其对响应资源进行缓存操作。
(4)Cache-Control:no-store
暗示请求或响应中包含机密信息,因此不进行缓存。
(5)Cache-Control:max-age=XXX(单位:秒)
当客户端发送的请求中包含max-age指令时,如果判定缓存资源的缓存时间比指定时间的数值更小,那么客户端就接收缓存的资源。
当服务器返回的响应中包含max-age指令时,缓存服务器不会再对资源有效性进行确认,用max-age指定的时间保存为缓存的最长时间。
如使用了该指令,在使用HTTP/1.1的缓存服务器中会直接忽略Expires首部字段,而在使用HTTP/1.0的缓存服务器上则相反。
(6)Cache-Control:s-maxage=XXX(单位:秒)
功能和max-age相同,不同点在于s-maxage指令只适用于供多位用户使用的公共缓存服务器(一般指代理)。使用该指令会直接忽略max-age与Expires首部字段。
(7)Cache-Control:min-fresh=XXX(单位:秒)
要求返回的资源至少在指定的时间内不会失效。
(8)Cache-Control:max-stale=XXX(单位:秒)
如果未指定参数值,那么无论资源失效多久客户端都接收;如果指定了数值,那么只要失效时间没超过指定时间客户端就接收。
(9)Cache-Control:only-if-cached
表示希望内容来自缓存,无论是否还有效。
(10)Cache-Control:must-revalidate
使用该指令,代理会向源服务器再次验证即将返回的响应缓存是否还有效。会忽略请求的max-stale指令。
(11)Cache-Control:proxy-revalidate
要求所有的缓存服务器在接收到客户端带有该指令的请求返回响应前,必须再次验证缓存有效性。
(12)Cache-Control:no-transform
无论在请求还是响应中,缓存都不能改变实体主体的媒体类型。
4.2.2 Connection
Connection首部字段具有以下几种功能:
(1)Connection:首部字段名
让代理在转发时删除指定的字段。
(2)Connection:close
HTTP/1.1版本的默认连接都是持久连接。当服务器端想明确断开连接时,则使用该指令。
(3)Connection:Keep-Alive
在旧版本的HTTP上维持持续连接时使用。
4.2.3 Date
表明创建HTTP报文的日期和时间。
HTTP/1.1协议使用如下格式(RFC1123中规定):
Date:Tue, 03 Jul 2012 04:40:59 GMT
之前的格式(RFC850中规定):
Date:Tue, 03-Jul-12 04:40:59 GMT
还有一种格式,与C标准库内的asctime()输出格式一致:
Date:Tue Jul 03 04:40:59 2012
4.2.4 Pragma
Pragma是HTTP/1.1之前版本的历史遗留字段,仅作为与HTTP/1.0的向后兼容而定义。唯一形式:Pragma:no-cache,仅用于客户端请求,表示要求服务器不返回缓存的资源。由于兼容性问题,一般和Cache-Control:no-cache一起出现。
4.2.5 Trailer
Trailer 是一个响应首部,允许发送方在分块发送的消息后面添加额外的元信息,这些元信息是随着消息主体的发送动态生成的,比如消息完整性校验,数字签名,或者后处理状态等。请求首部 TE 需要设置trailers来允许挂载字段。
使用格式:
(首部内)Trailer:Expire
(实体内容后)Expire:Wed, 21 Oct 2015 07:28:00 GMT\r\n
4.2.6 Transfer-Encoding
用于规定传输报文主体时采用的编码方式。属于逐跳首部,仅在两个节点间有效。可选gzip/compress/deflate/identity/chunked(分块)。
4.2.7 Upgrade
用于检测HTTP协议及其他协议及其他协议是否可使用更高的版本进行通信,其参数值用于指定一个新的协议。
Upgrade首部字段产生作用的Upgrade对象仅限于客户端和邻接服务器之间,属于逐跳首部字段,因此需要附加Connection:Upgrade字段。
4.2.8 Via
使用首部字段Via是为了追踪客户端与服务器之间的请求和响应报文的传输路径。报文通过代理或网关时,会先在首部字段Via中附加该服务器的信息,然后再进行转发。使用该字段可避免请求回环的发生,因此必须在经过代理时附加该首部字段内容。例:Via:1.0 gw.hackr.jp(Squid/3.1)。开头的1.0代表服务器的HTTP版本。
4.2.9 Warning
告知用户一些与缓存相关的问题的警告。格式如下:
Warning:警告码 警告的主机:端口号 “警告内容” [日期与时间]
4.3 请求首部字段
请求首部字段是从客户端往服务器端发送的请求报文中所使用的字段,用于补充请求的附加信息、客户端信息、对响应内容相关的优先级等内容。
4.3.1 Accept
用于通知服务器用户代理能够处理的媒体类型及媒体类型的相对优先级。示例如下:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,* / *;q=0.8
application/xhtml+xml和text/html为媒体类型,* / *表示任意媒体类型,q=0.3为优先级(0~1,1最大,默认为1,指的是出现在它前面的媒体类型的优先级,两者之间用分号隔开)。
4.3.2 Accept-Charset
用于通知服务器用户代理支持的字符集以及字符集的相对优先顺序。例:Accept-Charset:iso-8859-5, unicode-1-1;q=0.8
4.3.3 Accept-Encoding
用于通知服务器用户代理支持的内容编码及内容编码的相对优先级顺序。
几个内容编码的例子:gzip;compress;deflate;identity(不执行压缩)。
4.3.4 Accept-Language
用于告知服务器用户代理能够处理的自然语言集(英语、中文等)以及它们的相对优先级。
4.3.5 Authorization
用来告知服务器用户代理的认证信息。一般在接收到服务器的401状态码后加入。
4.3.6 Expect
用来告知服务器期望出现的某种特定行为。因服务器无法理解客户端的期望作出回应而发生错误时,会返回状态码417 Expectation Failed。例:Expect:100-continue
4.3.7 From
用来告知服务器使用用户代理的用户的电子邮件地址。通常,其使用目的就是为了显示搜索引擎等用户代理的负责人的电子邮件联系方式。使用代理时应尽可能包含From字段。例:From:info@hackr.jp
4.3.8 Host
用于告知服务器请求的资源所处的互联网主机名和端口号。Host首部字段在HTTP/1.1规范内是唯一一个必须被包含在请求内的首部字段。
Host首部字段和以单台服务器分配多个域名的虚拟主机的工作机制有很密切的关联,这是它必须存在的意义。请求被发送至服务器时,请求中的主机名会用IP地址直接替换解决。但如果相同的IP地址下部署着多个域名,那么服务器就会无法理解究竟是哪个域名对应的请求。此时就需要Host首部字段来明确指出请求的主机名。例:
Host:www.hackr.jp
若服务器未设定主机名,那直接发送空值即可,例:
Host:
4.3.9 If-Match
形如If-xxx这种样式的请求首部字段都称为条件请求。服务器接收到这种请求后,只有判断条件为真时才会执行。
If-Match用于告知服务器匹配资源所用的实体标记(ETag)值。此时的服务器无法使用弱ETag值。服务器会比对If-Match的字段值和资源的ETag值,仅当两者一致时才会执行请求。反之则返回状态码412 Precondition Failed。例:If-Match:“123456”。也可使用“*”作为字段值,这种情况下服务器会忽略ETag的值,只要资源存在就执行请求。
4.3.10 If-Modified-Since
例:If-Modified-Since:Tue, 03 Jul 2012 04:40:59 GMT
用于告知服务器,若资源在字段值指定的时间之后更新过就处理该请求。若未更新过则返回304 Not Modified。
4.3.11 If-None-Match
和If-Match相反,如果字段值指定的ETag值和请求资源的ETag值不相等则处理该请求。
4.3.12 If-Range
该字段一般配合Range首部字段使用,具有两重功能:
(1)若指定的字段值(ETag值或是时间)和请求资源的ETag值或时间一致,则作为范围请求处理,返回Range字段指定的范围。
(2)若指定的字段值(ETag值或是时间)和请求资源的ETag值或时间不一致,则忽略Range字段,返回完整资源,并告知客户端新的ETag值或时间。
4.3.13 If-Unmodified-Since
和If-Modified-Since相反,如果在指定的时间之后资源未发生更新才处理请求。若更新过了则返回412 Precondition Failed。
4.3.14 Max-Forwards
通过TRACE或是OPTIONS方法发送包含首部字段Max-Forwards的请求时,该字段以十进制整数的形式指定可经过的服务器最大数目,服务器在转发请求时会将该字段值减1。若收到的请求的该字段为0则不进行转发而直接返回响应。
4.3.15 Proxy-Authorization
接收到从代理服务器发来的认证质询时,客户端会发送包含首部字段Proxy-Authorization的请求,以告知服务器认证所需要的信息。
4.3.16 Range
告知服务器资源的指定范围。例:Range:bytes=5001-10000。服务器处理请求之后会返回206 Partial Content,无法处理范围请求时会返回200 OK及完整资源。
4.3.17 Referer
Referer 首部包含了当前页面的来源页面的地址,当前页面是通过此页面里的链接而进入的。Referer 首部允许服务器端识别是从哪里访问到它们的,可能会用此数据来进行统计分析、记录日志以及优化缓存策略等等。例:Referer:https://osu.ppy.sh/p/beatmaplist
4.3.18 TE
告知服务器客户端能够处理响应的传输编码方式和相对优先级。和Accept-Encoding很像,但用于传输编码,属于逐跳首部。例:TE:gzip, deflate;q=0.5
4.3.19 User-Agent
该字段会将创建请求的浏览器和用户代理名称等信息传达给服务器。
4.4 响应首部字段
响应首部字段是由服务器端向客户端返回的响应报文中所使用的字段,用于补充响应的附加信息。
4.4.1 Accept-Ranges
用来告知客户端服务器是否能处理范围请求,以指定获取服务器端某个部分的资源。可选的字段值有两种,可处理范围请求时指定其为bytes,反之则指定其为none。
4.4.2 Age
用来告知客户端消息对象在缓存代理中存贮的时长,以秒为单位。
4.4.3 ETag
ETag是资源的特定版本的标识符。服务器会为每份资源分配对应的ETag值。当资源更新时,ETag值也需要更新。
ETag值有强ETag值与弱ETag值之分。资源如果使用强ETag值,那么无论它发生多么细微的变化,它的ETag值都会改变。相反,如果使用弱ETag值,那么只有资源发生根本性改变,它的ETag值才会改变。使用弱ETag值需要在字段值最开始附加W/。
4.4.4 Location
用于将响应接收方引导至某个与请求URI位置不同的资源。一般配合3XX状态码使用。
4.4.5 Proxy-Authenticate
用于把由代理服务器所要求的认证信息发送给客户端。
4.4.6 Retry-After
用于告知客户端应该在多久之后再次发送请求。当与 503 (Service Unavailable,当前服务不存在) 响应一起发送的时候,表示服务下线的预期时长。当与重定向响应一起发送的时候,比如 301 Moved Permanently,表示用户代理在发送重定向请求之前需要等待的最短时间。
4.4.7 Server
用于告知客户端当前服务器上安装的HTTP服务器应用程序的信息。
4.4.8 Vary
用于让代理服务器决定,对于未来的一个请求头,应该用一个缓存的回复还是向源服务器请求一个新的回复。字段值为首部字段名。当代理服务器接收到带有Vary字段指定的的首部字段(假设为X)的请求报文时,如果使用的X的值和请求报文一致,那么就从缓存返回,否则要先从源服务器端获取资源再返回。
4.4.9 WWW-Authenticate
用于HTTP访问认证,告知客户端适用于访问请求URI所指定资源的认证方案(Basic或是Digest)和带参数提示的质询(challenge)。状态码401 Unauthorized响应中,肯定带有该字段。
4.5 实体首部字段
实体首部字段是包含在请求报文和响应报文中的实体部分所使用的首部,用于补充内容的更新时间等与实体相关的信息。
4.5.1 Allow
用于通知客户端请求的URI指定的资源支持的所有HTTP方法。当服务器接收到不支持的HTTP方法时,会 以状态码405 Method Not Allowed作为响应返回。与此同时,还会把所有支持的HTTP方法写入首部字段Allow。
4.5.2 Content-Encoding
用于告知客户端服务器对实体的主体部分选用的内容编码方式。内容编码是指在不丢失实体信息的前提下所进行的压缩。
4.5.3 Content-Language
用于告知客户端实体主体使用的自然语言。
4.5.4 Content-Length
表明了实体主体部分的大小(单位:字节)。如果对实体主体进行了内容编码传输,就不能再使用该字段。计算方法参考RFC2616的4.4。
4.5.5 Content-Location
给出与报文主体部分相对应的URI。Location 与 Content-Location是不同的,前者(Location )指定的是一个重定向请求的目的地址(或者新创建的文件的URL),而后者( Content-Location) 指向的是可供访问的资源的直接地址,不需要进行进一步的内容协商。Location 对应的是响应,而Content-Location对应的是要返回的实体。
4.5.6 Content-MD5
该首部字段的字段值是一串由MD5算法生成的值,目的在于检查报文主体在传输过程中是否保持完整,以及确认传输到达。需要对报文主体执行MD5算法获得128位二进制数,再通过Base64编码后再写入。
4.5.7 Content-Range
告知客户端返回的实体部分在原资源中所占的范围。例:
Content-Range:bytes 5001-10000/10000表示发送的是原资源的第5001-10000字节,并且资源总长度为10000字节。
4.5.8 Content-Type
说明实体主体内对象的媒体类型。例:
Content-Type: text/html; charset=utf-8表示媒体类型为text/html,字符编码标准为UTF-8。
4.5.9 Expires
用于将资源失效的日期告诉客户端。缓存服务器在接收到含有Expires的字段的响应时,会对响应进行缓存。如果接收到请求的时间超过了该字段的值,则会转向源服务器请求资源。
如果源服务器不希望缓存服务器缓存资源,可写入与Date相同的值。
如果首部中有Cache-Control:max-age=XXX指令,则会优先处理该指令。
4.5.10 Last-Modified
用于指明资源最终修改的时间。
4.6 为Cookie服务的首部字段
4.6.1 Set-Cookie
用于服务器向客户端传递Cookie。可以同时设置多个。支持字段值如下:
- NAME=VALUE:赋予这个Cookie名称以及其值(必须)。
- expires=DATE:Cookie有效期(不明确指定则默认为浏览器关闭前为止)。
- path=PATH:将服务器上的文件目录作为Cookie的适用对象(若不指定则默认为文档所在文件目录)。例:若设置path=/restricted,那么cookie将只应用于服务器的/restricted目录下。
- domain=域名:作为Cookie适用对象的域名(不指定默认为创建Cookie的服务器的域名)。例:若设置domain=.foo.example.com,那么cookie会在访问所有xxx.foo.example.com时被发送。
- Secure:仅在HTTPS安全通信时才发送Cookie。
- HttpOnly:使Cookie不能被JavaScript脚本访问。
实例:
Set-Cookie: BDRCVFR[Fc9oatPmwxn]=XXXXXXXXXX; path=/; domain=.baidu.com
BDSVRTM=182; path=/
BD_HOME=1; path=/
H_PS_PSSID=XXXX_XXXXX; path=/; domain=.baidu.com
4.6.2 Cookie
用于客户端发送请求报文时附带Cookie,同样可同时设置多个。格式为若干个用分号隔开的NAME=VALUE。
5 HTTPS
5.1 HTTP存在的安全性问题
HTTP具有以下安全性问题:
- 通信使用明文(不加密),内容可能会被窃听。
- 不对通信方的身份进行验证,可能遭遇伪装。
- 无法证明报文的完整性,收到的报文可能已遭篡改。
为了防止这些弊端,有必要使用HTTPS。
5.2 HTTPS简介
HTTPS全称HTTP Secure,是HTTP加上了加密处理、认证以及完整性保护而形成的。HTTPS并非是应用层的一种新协议,只是HTTP通信接口部分用SSL(Secure Socket Layer)和TLS(Transport Layer Security)代替而已。HTTP直接和TCP通信,而HTTPS先和SSL通信,再由SSL与TCP通信。
5.3 HTTPS使用的安全通信技术
5.3.1 密钥加密技术
使用密钥的目的是对报文的内容进行加密和解密,防止报文内容遭到窃听。近代的加密方法中加密算法是公开的,而密钥是保密的。这种方式使得加密方法的安全性得到了保证。根据加密和解密使用密钥的方式,密钥加密技术可分为以下几种:
(1)共享密钥加密:加密和解密同用一把密钥,又称为对称密钥加密。用这种方式进行通信的过程如下:
假设两个用户A,B进行通信,A先发送信息给B,然后B发送信息给A。
- A先用密钥k1加密一条信息,使之变成密文c1;
- A把密钥k1发送给B;(此时如果密钥被截获,截获方就可以解密并读取密文)
- A把密文c1发送给B;
- B用密钥k1解密,并读取解密后的信息
- B用密钥k2加密一条信息,使之变成密文c2;
- B把密钥k2发送给A;
- B把密文c2发送给A;
- A用密钥k2解密,并读取解密后的信息。
使用这种方式进行安全通信的前提是密钥能够安全传输,而这一点是无法保证的(如果能保证这一点,那么根本就无需加密)。
(2)公开密钥加密:加密和解密使用两把不同的密钥,又称为非对称密钥加密。加密时使用的是公开密钥,任何人都可以获得,而解密时使用的是私有密钥,不能泄露给其他人。用这种方式进行通信的过程如下:
假设两个用户A,B进行通信,A先发送信息给B,然后B发送信息给A。
- B先产生一对密钥k1a和k1b,前者用来加密,后者用来解密;
- B把密钥k1a发送给A;(因为k1a只能用来加密,截获方无法通过它来解密并读取密文)
- A用密钥k1a加密一条信息,使之变成密文c1;
- A把密文c1发送给B;
- B用密钥k1b解密,并读取解密后的信息;
- A产生一对密钥k2a和k2b,前者用来加密,后者用来解密;
- A把密钥k2a发送给B;
- B用密钥k2a加密一条信息,使之变成密文c2;
- B把密文c2发送给A;
- A用密钥k2b解密,并读取解密后的信息;
由于进行解密的私有密钥始终不参与传输,单独的加密密钥即使被截获也没有意义,因此这种方式的安全性是有保障的。
(3)混合加密方式:综合了以上两种方式的优点(共享密钥方式的速度以及公开密钥方式的安全性)。简单来讲,就是利用公开密钥方式安全地传输在接下来的通信中会使用的密钥,然后再使用共享密钥方式进行内容的传输。
5.3.2 数字证书认证
公开密钥方式存在这样一个漏洞:无法证明公开密钥本身没有遭到篡改。如果公开密钥在传输过程中被篡改,那么报文内容还是会遭到篡改者的窃听。过程如下:
假设两个用户A,B进行通信,A先发送信息给B,然后B发送信息给A。
- B先产生一对密钥k1a和k1b,前者用来加密,后者用来解密;
- B把k1a发送给A,过程中被中间人C截获。
- C产生一对假密钥k3a和k3c,前者用来加密,后者用来解密,并把k3a传输给A;
- A用k3a加密一条信息,使之变成密文c3;
- A把c3发送给B,过程中被中间人C截获;
- C用k3c解密,并窃取了解密后的信息;
- C对这条信息进行篡改,并使用真密钥k1a重新加密,使之变成密文c1;
- C把c1发送给B;
- B用k1b可以解密c1,但是内容已经遭到窃听和篡改。
问题的根本原因在于公开密钥缺少一种认证方式,接收到密钥的一方无法判别密钥的来源。为了解决这个问题,一种提供第三方认证服务的机构——数字证书认证机构(CA,Certificate Authority)出现了。
CA处于客户端与服务器双方都可信赖的第三方机构的立场上。它通过对公开密钥颁发公开密钥证书来证明公开密钥的真实性。CA的业务流程大致如下:
- 服务器把自己的公开密钥登录至CA;
- CA用自己的私有密钥向服务器的公开密码部署数字签名并颁发公钥证书(简称证书);
- 服务器将这份CA颁发的证书发送给客户端;
- 客户端拿到证书后,使用CA的公开密钥验证证书上的数字签名,以确认服务器的公开密钥的真实性。一旦验证通过,客户端就可明确两件事:认证服务器的公开密钥的是真实有效的数字证书认证机构;服务器的公开密钥是值得信赖的。
- 客户端使用服务器的公开密钥对信息进行加密后发送给服务器端;
- 服务器端用自己的私有密钥对信息进行解密。
这里存在一个问题:客户端如何能够获得可靠的CA公开密钥。如果依赖通信手段,那么又回到了问题的原点。这里采取的方式是由浏览器开发商在自己的浏览器中植入常用认证机关的公开密钥。
HTTPS中还可以使用客户端证书进行客户端认证,证明服务器正在通信的对方始终是预料之内的客户端,作用和服务器证书一致。由于客户端证书需要付费购买,因此一般只在特定的,可以支撑客服端证书费用的业务中使用,如网上银行等。
5.4 HTTPS握手过程
下面是HTTPS的身份认证(握手)过程:
- 客户端的浏览器向服务器传送客户端SSL协议的版本号,加密算法的种类,产生的随机数,以及其他服务器和客户端之间通讯所需要的信息。
- 服务器向客户端传送SSL协议的版本号,加密算法的种类,随机数以及其他相关信息,同时服务器还将向客户端传送自己的证书。
- 客户利用服务器传过来的信息验证服务器的合法性,服务器的合法性包括:证书是否过期,发行服务器证书的CA 是否可靠,CA的公开密钥是否能验证证书上的数字签名,服务器证书上的域名是否和服务器的实际域名相匹配。如果合法性验证没有通过,通讯将断开;如果合法性验证通过,将继续进行步骤4。
- 用户端随机产生一个用于后面通讯的对称密码(即共享密钥加密时使用的密钥),然后用服务器的公钥(服务器的公钥从步骤2中的服务器的证书中获得)对其加密,然后将加密后的“预主密码”传给服务器。
- 如果服务器要求客户的身份认证(在握手过程中为可选),用户可以建立一个随机数然后对其进行数据签名,将这个含有签名的随机数和客户自己的证书以及加密过的“预主密码”一起传给服务器。
- 如果服务器要求客户的身份认证,服务器必须检验客户证书和签名随机数的合法性,具体的合法性验证过程包括:客户的证书使用日期是否有效,为客户提供证书的CA 是否可靠,发行CA 的公钥能否正确解开客户证书的发行CA 的数字签名,检查客户的证书是否在证书废止列表(CRL)中。检验如果没有通过,通讯立刻中断;如果验证通过,服务器将用自己的私钥解开加密的“预主密码”,然后执行一系列步骤来产生主通讯密码(客户端也将通过同样的方法产生相同的主通讯密码)。
- 到这里为止,客户端和服务器端获得了相同的主通讯密码,之后的通讯在这个密码的基础上进行。在SSL通信过程中还要完成数据通讯的完整性,防止数据通讯中的任何变化。
- 客户端向服务器端发出信息,指明后面的数据通讯将使用的步骤7中的主密码为对称密钥,同时通知服务器客户端的握手过程结束。
- 服务器端向客户端发出信息,指明后面的数据通讯将使用的步骤7中的主密码为对称密钥,同时通知客户端服务器端的握手过程结束。
- SSL 的握手部分结束,SSL 安全通道的数据通讯开始,客户和服务器开始使用相同的对称密钥进行数据通信,同时进行通讯完整性的检验。
6 HTTP身份认证
6.1 何为认证
认证即为确认访问者的身份,并依次为依据判断访问者是否拥有访问某些资源的权限。
6.2 HTTP使用的认证方式
6.2.1 BASIC认证
BASIC认证(基本认证)是从HTTP/1.0开始就有的认证方式,至今还有部分网站使用。步骤如下:
- 当请求的资源需要BASIC认证时,服务器会随状态码401 Authorization Required返回带WWW-Authenticate字段的响应,字段内包含认证的方式(BASIC)及Request-URI安全域字符串(realm)。
- 接收到状态码401的客户端为了通过BASIC认证,需要将用户ID及密码发送给服务器。发送的字符串内容由用户ID和密码组成,中间以冒号连接后,再经过Base64编码处理。当用户代理是浏览器时,只需输入用户ID和密码即可,后续工作由浏览器完成。
- 接收到包含首部字段Authorization请求的服务器,会对认证信息的正确性进行验证,如验证通过则返回一条包含Request-URI资源的响应。
BASIC认证不够灵活,而且提供的安全性等级也不够,因此不常用。
6.2.2 DIGEST认证
DIGEST认证从HTTP/1.1起出现,同样使用质询/响应模式(challeng/response),但不会像BASIC认证一样发送明文密码。它的核心思想是使用一种叫nonce的随机数字符串,双方约好对哪些信息进行哈希运算即可完成双方身份的验证。步骤如下:
- 请求须认证的资源时,服务器会随着状态码401 Authorization Required返回带WWW-Authenticate首部字段的响应。WWW-Authenticate首部字段内必须包含realm和nonce两个字符串,其中nonce即为认证所需的临时质询码。
- 接收到401状态码的客户端,返回的响应中包含DIGEST认证必须的首部字段Authorization信息,包含username,realm,nonce,uri,response等信息。其中response即为经过MD5运算后的密码字符串(响应码)。
- 接收到包含首部字段Authorization请求的服务器,会确认认证信息的正确性,认证通过后则返回包含Request-URI资源的响应。同时,还会在首部字段Authentication-Info中写入一些认证成功的相关信息。
DIGEST提供的安全等级高于BASIC,但和HTTPS相比仍旧很弱,因此也不常用。
6.2.3 SSL客户端认证
SSL客户端认证是借由HTTPS的客户端证书完成认证的方式。步骤如下:
- 接收到需要认证资源的请求,服务器发送Certificate Request报文,要求客户端提供客户端证书;
- 用户选择将发送的客户端证书后,客户端把证书信息以Client Certificate报文方式发送给服务器。
- 服务器验证客户端证书,验证通过后取得证书内的公开密钥,之后进行HTTPS通信。
由于客户端证书需要付费购买,这种认证方式的适用范围受到了很大限制。
6.2.4 基于表单认证
由于使用上的便利性和安全性问题,HTTP协议提供的BASIC和DIGEST认证方式很少使用。SSL虽然安全性强,但由于导入以及费用问题,目前还尚未普及。因此,Web应用程序各自实现了基于表单的认证方式。多数情况下,用户需要输入用户ID和密码等信息并发送给Web应用程序,根据认证结果来决定认证是否成功。
表单认证本身是通过服务器端的Web应用程序将客户端发过来的ID和密码与之前登录过的信息做匹配来进行验证的。但鉴于HTTP是无状态协议,之前已认证成功的用户状态无法在协议层面保存下来,即使当该用户下一次继续访问,也无法区分他和其他用户。为解决这个问题,一般会使用Cookie来管理Session(会话)。步骤如下:
- 客户端把用户ID和密码等登录信息放入报文的实体部分,通常是以POST方法把请求发送给服务器,此时会使用HTTPS通信来进行HTML表单画面的显示和用户数据的发送。
- 服务器会发放用以识别用户的Session ID,通过验证客户端发送过来的登录信息进行身份认证,然后把用户的认证状态与Session ID绑定后记录在服务器端。向客户端返回响应时,会在首部字段Set-Cookie内写入Session ID。
- 客户端接收到服务器端发来的Session ID后,会将其作为Cookie保存在本地。下次向服务器发送请求时,浏览器会自动发送Cookie,所以Session ID也会随之发送到服务器。服务器根据Session ID识别用户和登录状态。
本文详细介绍了HTTP的基础知识,包括HTTP的特性、URI与URL的区别、HTTP请求与响应报文的结构,以及HTTP状态码和首部字段。特别强调了HTTP方法如GET、POST、PUT等,状态码200、404和500的含义,以及HTTP/1.1中通用首部字段如Cache-Control、Connection的作用。此外,还涵盖了HTTPS的使用、安全性问题和身份认证方式。
1077

被折叠的 条评论
为什么被折叠?



