######################################## HTTP ######################################## - HTTP 是应用层协议 - HTTP 用于客户端和服务端之间进行通信 在应用 HTTP 协议时,必定是一端为客户端,一端为服务端。其中请求资源的一端称为客户端,提供资源响应的一端为服务端。一个 HTTP 链接必定是由客户端发起的。 - HTTP 是无状态协议 HTTP 协议自身不对请求和响应之间的通信状态进行保存 - HTTP 使用 URI 定位资源 资源请求的方式有两种: .. code-block:: none GET http://abc.cn/index.html HTTP/1.1 或者是: .. code-block:: none GET /index.html HTTP/1.1 Host: abc.cn 如果不是访问资源而是对服务器本身发起请求,可以使用 \* 来代替 URI。下面是一个查询 HTTP 服务器支持的 HTTP 方法种类: .. code-block:: none 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 是无状态的,服务器对于每条连接的处理方式都是一样的。但是通过让客户端在请求报文中携带一些数据来表明身份,服务器就可以对不同的客户端提供不同的服务 Cookie ======================================== 服务器可以在报文中使用 Set-Cookie 在客户端中储存键值对,而客户端在发送 HTTP 请求时带上这些键值对,服务器就可以识别客户端的身份。 例如在一次 HTTP 请求中,客户端先发出请求,然后服务器设置 Cookie,之后客户端就在 HTTP 请求中带上这些 Cookie: 客户端请求服务 :: GET /reader/ HTTP/1.1 Host: abc.cn 服务器在响应报文中设置 Cookie :: HTTP/1.1 200 OK Data: Thu, 12 Jul 2012... Server: Nginx Content-Type: text/plain; charset=UTF-8 客户端在新的请求中携带 Cookie :: GET /image/ HTTP/1.1 Host: abc.cn Cookie: sid=1234 压缩传输和分块传输 **************************************** HTTP 的实体部可以通过压缩再进行传输,这要求在首部指明压缩方式 :: Content-Encoding:gzip 压缩方式常用的有四种:gzip、compress、deflate(zlib)、identity(不进行编码) 在 HTTP 通信过程中,一次传输过程完成前数据是无法使用的,因此在传输大容量数据时,通过把数据进行分块,能够让浏览器逐步显示页面。这种把实体分块的功能称为 :abbr:`分块传输编码 (Chunked Transfer Coding)` ,其中每个小块被称为一个 Chunk 多类型数据的传输 **************************************** MIME 拓展中使用了一种称为 :abbr:`多部分对象集合 (Multipart)` 的方法,用来在一次传输中容纳多份不同类型的数据。HTTP 也采用了此方法。 多对象集合包含对象如下: +----------------------+-----------------------------------------------+ | MIME 类型 | 作用 | +----------------------+-----------------------------------------------+ | multipart/form-data | 上传表单文件时使用 | +----------------------+-----------------------------------------------+ | multipart/byteranges | 状态码 206 响应报文包含了多个范围的内容时使用 | +----------------------+-----------------------------------------------+ 对于 multipart/form-data 来说,一个 **POST** 请求示例如下 [#form-data]_ :: 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 是自定义的分割符,而每次数据的形式为 :: <上个部分数据> --分隔符 <首部字段> --分隔符 <下个部分数据> --分隔符-- 内容之间的分隔符形式为 *--分隔符* ,结尾的分隔符为 *--分隔符--* 对于 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-- .. [#form-data] `深入解析 multipart/form-data `_ 范围请求 **************************************** 范围请求使得客户端能够指定只传输需要的实体部分字节流,这就实现了 HTTP 协议中的断点重传,在 HTTP 中,这种只传输指定范围字节的请求称谓 :abbr:`范围请求 (Range Request)` 一个使用范围请求的请求头例子为 :: 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 实际上和重定向无关。在未满足请求报文中的附带条件 [#condition]_ 时,响应报文不包含实体部 | +---------------------------+---------------------------------------------------------------------------------------------+ | 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 | 服务器超负载或者正在停机维护,现在无法响应请求 | +---------------------------+---------------------------------------------------------------------------------------------+ .. note:: 实际上,很多浏览器将 301、302 视同 303 进行处理,尽管 301、302 不允许将 POST 改为 GET .. [#condition] 附带条件的请求指的是 GET 请求报文中包含了 If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since 至少其中之一 协同技术 **************************************** 服务器还催生了一些其它技术。例如虚拟主机、代理、隧道等。 虚拟主机:将多个域名映射到一台主机上,然后服务器根据请求报文中的 Host 将请求转发给对应的网站处理。这样就可以使用一台主机搭建多个 Web 站点。 代理:代理服务器充当中间人,将客户端的请求发送给服务器,然后将服务器的响应报文发给客户端。如果在转发过程中没有更改报文,那么称为 **透明代理** 。如果代理会预缓存资源,那么称为 **缓存代理** 网关:网关与代理类似,但是网关能将使服务器提供非 HTTP 协议服务。例如在客户端和网关之间进行加密等。 隧道:隧道按要求建立一条与其它服务器的通信链路,从而保障通信的安全性 HTTPS **************************************** 相比 HTTP 通过 TCP 发送报文而言,HTTPS 通过 SSL 发送报文。而 SSL 提供了双端加密。 .. hint:: SSL 是应用层协议,而不是运输层协议。SSL 使用 TCP 作为运输层协议 在 SSL 的通信过程中。SSL 首先使用非对称加密来构建传输通道,然后双方约定对称加密密码,并使用对称密码来传输内容。之所以如此,是因为非对称加密安全性高但是加密解密慢,而对称加密安全性低,却加密解密快。 在 HTTPS 通信过程中,首先双方交换公钥,然后再进行 SSL 加密过程。 身份认证 **************************************** CSRF **************************************** :abbr:`CSRF (Cross-Site Request Forgery)` 即跨站请求伪造,是指利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其点击恶意链接或包含攻击代码的页面 [#wcsrf]_ 以下哪个是可以执行的CSRF漏洞的修复方案(A)[#bcsrf]_ A. 检测HTTP referer 字段同域 B. 过滤单引号或尖括号 C. 在每个请求里面都添加验证码校验 D. cookie 关键字段设置HttpOnly属性 .. [#wcsrf] `CSRF跨站请求伪造漏洞修复方案 `_ .. [#bcsrf] `以下哪个是可以执行的CSRF漏洞的修复方案 `_