HTTP

  • HTTP 是应用层协议

  • HTTP 用于客户端和服务端之间进行通信

    在应用 HTTP 协议时,必定是一端为客户端,一端为服务端。其中请求资源的一端称为客户端,提供资源响应的一端为服务端。一个 HTTP 链接必定是由客户端发起的。

  • HTTP 是无状态协议

    HTTP 协议自身不对请求和响应之间的通信状态进行保存

  • HTTP 使用 URI 定位资源

    资源请求的方式有两种:

    GET http://abc.cn/index.html HTTP/1.1
    

    或者是:

    GET /index.html HTTP/1.1
    Host: abc.cn
    

    如果不是访问资源而是对服务器本身发起请求,可以使用 * 来代替 URI。下面是一个查询 HTTP 服务器支持的 HTTP 方法种类:

    OPTIONS * HTTP/1.1
    

HTTP 方法

所谓 HTTP 方法,就是 客户端 在请求报文中用来告知服务器自己意图的方式。HTTP 拥有的方法如下:

方法

作用

解释

GET

获取资源

用来请求指定 URI 所表示的资源

POST

传输实体主体

用来向服务器发送数据

PUT

传输文件

在请求报文中包含文件内容,并保存到 URI 代表的位置

HEAD

获取报文受不

与 GET 类似,但是不获取报文主体,只获取报文头

DELETE

删除文件

删除 URI 所代表的资源

OPTIONS

询问支持的方法

向服务器查询针对 URI 所代表的资源的支持方法

TRACE

跟在路径

让服务器将之前的请求通信环回给客户端

CONNECT

要求用隧道协议廉洁代理

要求在于代理服务器通信时建立隧道

持久连接

在传统的 HTTP 连接中,每次发送资源都会建立一条新的 HTTP 连接。但是对于 HTML 这样包含很多资源的页面来说,重复地建立链接会导致效率低下,增加开销,因此,HTTP/1.1 提出了持久连接的概念

持久连接中,只要任意一端没有明确提出断开连接,就保持 TCP 连接状态。

持久连接使得一个 HTTP 连接可以发送多个资源,从而降低了创建和销毁 HTTP 连接的开销。

管线化

与 TCP 的滑动窗口类似,持久化连接允许一个 HTTP 连接中发送多个资源,而管线化则允许在没有得到相应时就发送下一个请求。这样就允许并发发送多个请求,而不是一个一个等待相应

状态管理

HTTP 是无状态的,服务器对于每条连接的处理方式都是一样的。但是通过让客户端在请求报文中携带一些数据来表明身份,服务器就可以对不同的客户端提供不同的服务

压缩传输和分块传输

HTTP 的实体部可以通过压缩再进行传输,这要求在首部指明压缩方式

Content-Encoding:gzip

压缩方式常用的有四种:gzip、compress、deflate(zlib)、identity(不进行编码)

在 HTTP 通信过程中,一次传输过程完成前数据是无法使用的,因此在传输大容量数据时,通过把数据进行分块,能够让浏览器逐步显示页面。这种把实体分块的功能称为 分块传输编码 ,其中每个小块被称为一个 Chunk

多类型数据的传输

MIME 拓展中使用了一种称为 多部分对象集合 的方法,用来在一次传输中容纳多份不同类型的数据。HTTP 也采用了此方法。

多对象集合包含对象如下:

MIME 类型

作用

multipart/form-data

上传表单文件时使用

multipart/byteranges

状态码 206 响应报文包含了多个范围的内容时使用

对于 multipart/form-data 来说,一个 POST 请求示例如下 1

POST /t2/upload.do HTTP/1.1
Content-Type:multipart/form-data; boundary=ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
Host: w.sohu.com

--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
Content-Disposition: form-data; name="city"

Santa colo
--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
Content-Disposition: form-data;name="desc"
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

...
--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
Content-Disposition: form-data;name="pic"; filename="photo.jpg"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary

... binary data of the jpg ...
--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC--

其中 boundary 是自定义的分割符,而每次数据的形式为

<上个部分数据>
--分隔符
<首部字段>
<CRLF>
<data>
--分隔符
<下个部分数据>
--分隔符--

内容之间的分隔符形式为 –分隔符 ,结尾的分隔符为 –分隔符–

对于 multipart/byteranges 来说,一个响应报文的示例为

HTTP/1.1 206 Partial Content
Date: Wed, 15 Nov 1995 06:25:24 GMT
Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
Content-Length: 1741
Content-Type: multipart/byteranges; boundary=THIS_STRING_SEPARATES

--THIS_STRING_SEPARATES
Content-Type: application/pdf
Content-Range: bytes 500-999/8000

...the first range...
--THIS_STRING_SEPARATES
Content-Type: application/pdf
Content-Range: bytes 7000-7999/8000

...the second range
--THIS_STRING_SEPARATES--
1

深入解析 multipart/form-data

范围请求

范围请求使得客户端能够指定只传输需要的实体部分字节流,这就实现了 HTTP 协议中的断点重传,在 HTTP 中,这种只传输指定范围字节的请求称谓 范围请求

一个使用范围请求的请求头例子为

GET /tip.jpg HTTP/1.1
Host www.abc.cn
Range: bytes =5001-10000

也可以传输 5001 之后全部的内容

Range: bytes=5001-

从起始到 3000 和 5000-7000 的多重范围

Range: bytes=-3000, 5000-7000

对于多重请求,相应状态码为 206。对于多重范围,相应报文的 MIME 格式为 multipart/byteranges。如果服务器无法响应范围请求,则会返回状态吗 200 OK 和完整报文

内容协商

服务器根据请求头可以返回合适的内容,例如根据请求头选择返回中文页面或者英文页面,这一过程称谓内容协商。内容协商需求的首部字段为:

  • Accept

  • Accept-Charset

  • Accept-Language

  • Content-Language

表单数据

表单中的 enctype 规定了以何种格式向服务器发送表单内容,有三种类型:

  • application/x-www-urlencoded

  • multipart/form-data

  • text-plain

其中 application/x-www-urlencoded 是默认类型

GET 请求只支持 ASCII 字符集,因此,如果要发送更大字符集的内容,应使用 POST 请求

一个使用 application/x-www-urlencoded 的示例为

POST / HTTP/1.1
Content-Type:application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: w.sohu.com
Content-Length: 21
Connection: Keep-Alive
Cache-Control: no-cache

txt1=hello&txt2=world

实际上就是把 GET 中的数据放到了 Body 中,与 GET 并无二致

HTTP 状态码

状态码代表了服务器对客户端请求的处理结果,写在了相应报文的首部。响应报文可以粗略地分为五类:

类别

原因

1xx

Informational(信息性状态码)

接受的请求正在处理

2xx

Success(成功状态码)

请求正常处理完毕

3xx

Redirection(重定向状态码)

需要进行附加操作以完成请求

4xx

Client Error(客户端错误状态码)

服务器无法处理请求

5xx

Server Error(服务器错误状态码)

服务器处理请求出错

除了 RFC 2616 记载的状态码外,WebDAV 所属的 RFC 4918 和 RFC 5842 等等也定义了大量状态码。只要遵循状态码类别的定义,即使改变 RFC 2616 定义的状态码,或者是自行创建状态码都是允许的。尽管如此,HTTP 常用的状态码只有 14 种:

状态码

含义

200 OK

客户端发送的请求被正常处理了

204 No Content

请求被正常处理,但是响应报文中不含实体的主体部分。一般发生在只需要从客户端发送信息的情况下

206 Partial Content

客户端发送的范围请求被正确处理

301 Moved Permanently

永久重定向。请求的资源被分配了新的 URI

302 Found

临时重定向。请求的资源被分配了新的 URI

303 See Other

与 302 类似。但是 303 要求客户端应当使用 GET 方法获取资源

304 Not Modified

304 实际上和重定向无关。在未满足请求报文中的附带条件 2 时,响应报文不包含实体部

307 Temporary Redirect

与 302 相同,但是要求不将 POST 变成 GET

400 Bad Request

请求报文中出现语法错误。此状态码在浏览器中视同 200 OK

401 Unauthorized

表示发送的请求需要有通过 HTTP 认证的认证信息。如果已经进行过一次认证,表明认证失败

403 Forbidden

表示对请求资源的访问被服务器拒绝了。理由 可 写在实体部

404 Not Found

服务器无法找到请求的资源。也可能是服务器拒绝请求并且不想说明理由

500 Internal Server Error

服务器在执行请求时发生了错误。也可能是服务器的 Bug 或者某些临时故障

503 Service Unavailable

服务器超负载或者正在停机维护,现在无法响应请求

备注

实际上,很多浏览器将 301、302 视同 303 进行处理,尽管 301、302 不允许将 POST 改为 GET

2

附带条件的请求指的是 GET 请求报文中包含了 If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since 至少其中之一

协同技术

服务器还催生了一些其它技术。例如虚拟主机、代理、隧道等。

虚拟主机:将多个域名映射到一台主机上,然后服务器根据请求报文中的 Host 将请求转发给对应的网站处理。这样就可以使用一台主机搭建多个 Web 站点。

代理:代理服务器充当中间人,将客户端的请求发送给服务器,然后将服务器的响应报文发给客户端。如果在转发过程中没有更改报文,那么称为 透明代理 。如果代理会预缓存资源,那么称为 缓存代理

网关:网关与代理类似,但是网关能将使服务器提供非 HTTP 协议服务。例如在客户端和网关之间进行加密等。

隧道:隧道按要求建立一条与其它服务器的通信链路,从而保障通信的安全性

HTTPS

相比 HTTP 通过 TCP 发送报文而言,HTTPS 通过 SSL 发送报文。而 SSL 提供了双端加密。

提示

SSL 是应用层协议,而不是运输层协议。SSL 使用 TCP 作为运输层协议

在 SSL 的通信过程中。SSL 首先使用非对称加密来构建传输通道,然后双方约定对称加密密码,并使用对称密码来传输内容。之所以如此,是因为非对称加密安全性高但是加密解密慢,而对称加密安全性低,却加密解密快。

在 HTTPS 通信过程中,首先双方交换公钥,然后再进行 SSL 加密过程。

身份认证

CSRF

CSRF 即跨站请求伪造,是指利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其点击恶意链接或包含攻击代码的页面 3

以下哪个是可以执行的CSRF漏洞的修复方案(A)[#bcsrf]_

  1. 检测HTTP referer 字段同域

  2. 过滤单引号或尖括号

  3. 在每个请求里面都添加验证码校验

  4. cookie 关键字段设置HttpOnly属性

3

CSRF跨站请求伪造漏洞修复方案

4

以下哪个是可以执行的CSRF漏洞的修复方案