HTTP

HTTP协议是基于TCP/IP协议的应用层协议。它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。

HTTP协议的特性

  • 客户端/服务端模式。HTTP协议规定了:

    • 在一条通信线路上必定有一端是客户端,另一端是服务器端。

    • 请求从客户端发出,服务器端响应请求并返回。也就是说,请求肯定是先从客户端开始建立通信的,服务器端在没有接收请求之前不会发送响应。

  • 无连接。请求时建连接、请求完释放连接,以尽快将资源释放出来服务其他客户端。

  • 无状态。协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。

HTTP/0.9

简介

  • 最早版本是1991年发布的0.9版。该版本极其简单,只有一个命令GET

  • 协议规定,服务器只能回应HTML格式的字符串,不能回应别的格式。

  • 服务器发送完毕,就关闭TCP连接。

HTTP/1.0

简介

  • 1996年5月发布, 引入了POST命令和HEAD命令。

  • 任何格式的内容都可以发送。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。

  • HTTP请求和回应的格式变化。除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据。

  • 其他的新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。

请求格式

GET / HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*

响应格式

HTTP/1.0 200 OK 
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84

<html>
  <body>Hello World</body>
</html>

Content-Type字段

HTTP/1.0版规定,头信息必须是 ASCII 码,后面的数据可以是任何格式。因此,服务器回应的时候,必须告诉客户端,数据是什么格式,这就是Content-Type字段的作用。

常见Content-Type字段:

  • text/plain

  • text/html

  • text/css

  • image/jpeg

  • image/png

  • image/svg+xml

  • audio/mp4

  • video/mp4

  • application/javascript

  • application/pdf

  • application/zip

  • application/atom+xml

这些数据类型总称为MIME type,每个值包括一级类型和二级类型,之间用斜杠分隔。

MIME type还可以在尾部使用分号,添加参数。如:Content-Type: text/html; charset=utf-8表明发送的是HTML,编码为UTF-8。

客户端请求的时候,可以使用Accept字段声明自己可以接受哪些数据格式。如:Accept: */*用于客户端声明自己可以接受任何格式的数据。

Content-Encoding字段

由于发送的数据可以是任何格式,因此可以把数据压缩后再发送。Content-Encoding字段说明数据的压缩方法。如:

  • Content-Encoding: gzip

  • Content-Encoding: compress

  • Content-Encoding: deflate

客户端在请求时,用Accept-Encoding字段说明自己可以接受哪些压缩方法。如:Accept-Encoding: gzip, deflate

缺点

HTTP/1.0 版的主要缺点是,每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。

TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(TCP 连接会随着时间进行自我调谐,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度,这种调谐则被称为 TCP 慢启动)。所以,HTTP 1.0版本的性能比较差。随着网页加载的外部资源越来越多,这个问题就愈发突出了。

为了解决这个问题,有些浏览器在请求时,用了一个非标准的Connection字段。

Connection: keep-alive

这个字段要求服务器不要关闭TCP连接,以便其他请求复用。服务器同样回应这个字段。

Connection: keep-alive

一个可以复用的TCP连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段,不同实现的行为可能不一致,因此不是根本的解决办法。

HTTP/1.1

1997年1月,HTTP/1.1 版本发布,只比 1.0 版本晚了半年。

持久连接

HTTP/1.1的最大变化,就是引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive

客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP连接。

Connection: close

目前,对于同一个域名,大多数浏览器允许同时建立6个持久连接。

管道机制

HTTP/1.1引入了管道机制(pipelining),即在同一个TCP连接里面,客户端可以同时发送多个请求。这样就进一步改进了HTTP协议的效率。

举例来说,客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送A请求,然后等待服务器做出回应,收到后再发出B请求。管道机制则是允许浏览器同时发出A请求和B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求。

Content-Length字段

用于声明本次回应(因为一个TCP连接可以传送多个回应)的数据长度,从而区分数据包是属于哪一个回应。

在HTTP/1.0中,Content-Length字段不是必需的,因为浏览器发现服务器关闭了TCP连接,就表明收到的数据包已经全了。

分块传输编码

使用Content-Length字段的前提条件是,服务器发送回应之前,必须知道回应的数据长度。对于比较耗时的动态操作来说,这意味着,服务器要等到所有操作完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用"流模式"(stream)取代"缓存模式"(buffer)。

因此,HTTP/1.1规定可以不使用Content-Length字段,而使用分块传输编码(chunked transfer encoding)。只要请求或回应的头信息有Transfer-Encoding字段,就表明回应将由数量未定的数据块组成。

Transfer-Encoding: chunked

其他功能

  • 新增动词方法:PUTPATCHHEADOPTIONSDELETE

  • 客户端请求的头信息新增了Host字段,用来指定服务器的域名。

缺点

虽然HTTP/1.1允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为“队头堵塞”(Head-of-line blocking)。

为了避免这个问题,只有两种方法:一是减少请求数,二是同时多开持久连接。这导致了很多的网页优化技巧,如:合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等。

HTTP/2

于2015年发布。

二进制分帧

为了在不改动 HTTP/1.x的语义、方法、状态码、URI 以及首部字段的情况下, 做到突破 HTTP1.x的性能限制,改进传输性能,实现低延迟和高吞吐量,HTTP/2在应用层(HTTP/2)和传输层(TCP or UDP)之间增加一个二进制分帧层。将所有传输的信息分割为更小的消息和帧(frame),并对它们采用二进制格式的编码 ,其中 HTTP1.x 的首部信息会被封装到 HEADER frame,而相应的 Request Body 则封装到 DATA frame 里面。

二进制分帧的优点:

  • 单连接多资源的方式,减少服务端的链接压力,内存占用更少,连接吞吐量更大。

  • 由于 TCP 连接的减少而使网络拥塞状况得以改善,同时慢启动时间的减少,使拥塞和丢包恢复速度更快。

多路复用

HTTP/2把HTTP协议通信的基本单位缩小为一个一个的帧,这些帧对应着逻辑流中的消息,并行地在同一个 TCP 连接上双向交换消息。因此 HTTP/2 可以很容易的去实现多流并行而不用依赖建立多个 TCP 连接。

首部压缩

HTTP/1.x不支持首部压缩,HTTP/2使用了专门为首部压缩而设计的HPACK算法。

服务端推送

服务端推送(Server Push)是一种在客户端请求之前发送数据的机制。在 HTTP/2中,服务器可以对客户端的一个请求发送多个响应。服务端推送让HTTP1.x时代使用内嵌资源的优化手段变得没有意义;如果一个请求是由你的主页发起的,服务器很可能会响应主页内容、logo 以及样式表,因为它知道客户端会用到这些东西。这相当于在一个 HTML 文档内集合了所有的资源,不过与之相比,服务器推送还有一个很大的优势:可以缓存!也让在遵循同源的情况下,不同页面之间可以共享缓存资源成为可能。

常见请求方法

方法

说明

GET

请求获取Request-URI所标识的资源

POST

在Request-URI所标识的资源后附加新的数据

PUT

请求服务器存储一个资源,并用Request-URI作为其标识

DELETE

请求服务器删除Request-URI所标识的资源

OPTIONS

请求查询服务器的性能,或者查询与资源相关的选项和需求

HEAD

请求获取由Request-URI所标识的资源的响应消息报头

TRACE

请求服务器回送收到的请求信息,主要用于测试或诊断

CONNECT

保留将来使用

状态码

状态码

说明

1xx

指示信息——表示服务器收到请求,需要请求者继续执行操作

2xx

成功——表示请求已被成功接收、理解、接受

3xx

重定向——要完成请求必须进行更进一步的操作

4xx

客户端错误——请求有语法错误或请求无法实现

5xx

服务器端错误——服务器未能实现合法的请求

常见状态码

状态码

英文表述

说明

200

OK

请求成功。一般用于GET与POST请求

204

No Content

无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档

301

Moved Permanently

永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替

302

Found

临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI

400

Bad Request

客户端请求的语法错误,服务器无法理解

401

Unauthorized

请求要求用户的身份认证

403

Forbidden

服务器理解请求客户端的请求,但是拒绝执行此请求

404

Not Found

服务器无法根据客户端的请求找到资源(网页)

502

Bad Gateway

作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应

HTTP幂等性

  • GET用于获取资源,不应有副作用,所以是幂等的。

  • POST用于创建资源,所对应的URI并非创建的资源本身,而是去执行创建动作的操作者,有副作用,不满足幂等性。

  • PUT用于创建或更新操作,所对应的URI是要创建或更新的资源本身,有副作用,它应该满足幂等性。

  • DELETE用于删除资源,有副作用,但它应该满足幂等性。

会话跟踪

什么是会话

客户端打开与服务器的连接发出请求到服务器响应客户端请求的全过程称之为会话。

什么是会话跟踪

会话跟踪指的是对同一个用户对服务器的连续的请求和接受响应的监视。

为什么需要会话跟踪

HTTP协议是无状态协议,无法保存客户信息,为了在请求中判断是否为同一用户,所以需要会话跟踪技术。

会话跟踪常用方法

URL重写

URL重写的技术就是在URL结尾添加一个附加数据以标识该会话,把会话ID通过URL的信息传递过去,以便在服务器端进行识别不同的用户。

隐藏表单域

将会话ID添加到HTML表单元素中提交到服务器,此表单元素并不在客户端显示。

Cookie是Web服务器发送给客户端的一小段信息,客户端请求时可以读取该信息发送到服务器端,进而进行用户的识别。对于客户端的每次请求,服务器都会将Cookie发送到客户端,在客户端可以进行保存,以便下次使用。

客户端可以采用两种方式来保存这个Cookie对象,一种方式是保存在客户端内存中,称为临时Cookie,浏览器关闭后这个Cookie对象将消失。另外一种方式是保存在客户机的磁盘上,称为永久Cookie。以后客户端只要访问该网站,就会将这个Cookie再次发送到服务器上,前提是这个Cookie在有效期内,这样就实现了对客户的跟踪。

Cookie是可以被客户端禁用的。

Session

服务器端创建一个session对象,产生一个sessionID来标识这个 session 对象,然后将这个sessionID放入到 Cookie 中发送到客户端,下一次访问时,sessionID会发送到服务器,在服务器端进行识别不同的用户。

每一个用户都有一个不同的session,各个用户之间是不能共享的,是每个用户所独享的,在session中可以存放信息。

Session的实现依赖于Cookie,如果Cookie被禁用,那么session也将失效(但是可以通过其他方式实现,比如在url中传递sessionID)。

  • Session保存于服务器端,Cookie保存于客户端。

  • Cookie只是实现Session的其中一种方案。虽然是最常用的,但并不是唯一的方法。

  • Session相较于Cookie更安全。

  • Cookie不仅可以用于会话跟踪,还可以用于保存用户喜好或者用户名、密码等。

跨站攻击

CSRF(Cross-site request forgery,跨站请求伪造)

即伪造请求,冒充用户在站内的正常操作。

如何防御CSRF攻击

  • 验证码 :简单有效的防御方法,但会严重影响用户体验,不建议使用。

  • 检测Referer:一般用于监控 CSRF 攻击的发生,而不用来抵御攻击。

  • Token:目前的主流做法。

XSS(Cross Site Scripting,跨站脚本攻击)

XSS 全称“跨站脚本”,是注入攻击的一种。其特点是不对服务器端造成任何伤害,而是通过一些正常的站内交互途径,例如发布评论,提交含有 JavaScript 的内容文本。这时服务器端如果没有过滤或转义掉这些脚本,作为内容发布到了页面上,其他用户访问这个页面的时候就会运行这些脚本。

如何防御XSS攻击

理论上,所有可输入的地方没有对输入数据进行处理的话,都会存在 XSS 漏洞,漏洞的危害取决于攻击代码的威力,攻击代码也不局限于 script。防御 XSS 攻击最简单直接的方法,就是过滤用户的输入。

最后更新于

这有帮助吗?