HTTP超文本传输协议
HTTP协议概述
HTTP 是一种能够获取如 HTML 这样的网络资源的通讯协议(超文本传输协议)。
是一种 client-server
协议,客户端和服务端通过交换各自的消息进行交互。由像浏览器这样的客户端发出的消息叫做 request
,被服务端响应的消息叫做 response
。
一个完整的 Web 文档通常是由不同的子文档拼接而成的,像是文本、图片、视频、脚本等等。
HTTP 是无状态,有会话的
HTTP 是无状态的:在同一个连接中,两个执行成功的请求之间是没有关系的。
这就带来了一个问题,用户没有办法在同一个网站中进行连续的交互,比如在一个电商网站里,用户把某个商品加入到购物车,切换一个页面后再次添加了商品,这两次添加商品的请求之间没有关联,浏览器无法知道用户最终选择了哪些商品。
而使用 HTTP 的头部扩展,HTTP Cookies 就可以解决这个问题。把 Cookies 添加到头部中,创建一个会话让每次请求都能共享相同的上下文信息,达成相同的状态。
注意,HTTP 本质是无状态的,使用 Cookies 可以创建有状态的会话。
HTTP连接
一个连接是由传输层来控制的,这从根本上不属于 HTTP 的范围。HTTP 并不需要其底层的传输层协议是面向连接的,只需要它是可靠的,或不丢失消息的(至少返回错误)。在互联网中,有两个最常用的传输层协议:TCP 是可靠的,而 UDP 不是。因此,HTTP 依赖于面向连接的 TCP 进行消息传递,但连接并不是必须的。
在客户端(通常指浏览器)与服务器能够交互(客户端发起请求,服务器返回响应)之前,必须在这两者间建立一个 TCP 链接,打开一个 TCP 连接需要多次往返交换消息(因此耗时)。HTTP/1.0 默认为每一对 HTTP 请求/响应都打开一个单独的 TCP 连接。当需要连续发起多个请求时,这种模式比多个请求共享同一个 TCP 链接更低效。
为了减轻这些缺陷,HTTP/1.1 引入了流水线(被证明难以实现)和持久连接的概念:底层的 TCP 连接可以通过Connection
头部来被部分控制。HTTP/2 则发展得更远,通过在一个连接复用消息的方式来让这个连接始终保持为暖连接。
HTTP 对 TCP 连接的使用,分为两种方式:俗称“短连接”和“长连接”。
HTTP/1.1 默认使用长连接(持久化连接)。
HTTP建立连接的过程
- 在TCP连接上发送HTTP报文;根据规则, 只有低层协议建立之后才能进行高层协议的连接
- 发送请求行,
GET /dir/xx.php HTTP/1.1
- 发送请求头,浏览器发送一行空白行来告知服务器结束请求头信息发送
- 服务器响应, HTTP/1.1 200 OK(协议版本号和HTTP状态码)
- 服务器发送响应头,服务器自己的相关信息(同样用空白行表示结束响应头)
- 服务器向浏览器发送数据, 以
Content-Type
响应头信息所描述的格式发送用户所请求的实际数据 - 服务器关闭TCP连接,如果请求头或响应头加了这行
Connection:keep-alive
,会保持连接
HTTP报文
请求(Request)
相关信息
Method:请求方法
Path:访问网站的路径
Version:HTTP协议版本号
Headers:HTTP请求头
响应(Response)
相关信息
Version:HTTP协议版本号
Status code:状态码,告知对应请求执行成功或失败,以及失败的原因。
Status message:状态信息,这个信息是非权威的状态码描述信息,可以由服务端自行设定。
Headers:HTTP响应头
HTTP请求方法
请求方法 | 作用 |
---|---|
GET | 请求指定的资源,只用于获取数据 |
POST | 发送数据给服务器。请求主体的类型由 Content-Type 首部指定 |
OPTIONS | 用于获取目的资源所支持的请求方法 |
HEAD | 请求资源的头部信息,获取资源大小,响应不包含响应体,可以节约带宽资源 |
PUT | 使用请求中的负载创建或者替换目标资源 |
DELETE | 删除指定的资源 |
TRACE | 实现沿通向目标资源的路径的消息环回(loop-back)测试,提供了一种实用的 debug 机制 |
PATCH | 用于对资源进行部分修改 补丁 |
CONNECT | 开启一个客户端与所请求资源之间的双向沟通的通道。可以用来创建隧道(tunnel) |
警告
PUT
与 POST
方法的区别在于,PUT 方法是幂等的:调用一次与连续调用多次是等价的(即没有副作用),而连续调用多次 POST 方法可能会有副作用,比如将一个订单重复提交多次。
如果目标资源不存在,并且 PUT 方法成功创建了一份,那么源头服务器必须返回201
(Created
) 来通知客户端资源已创建。
HTTP/1.1 201 Created
Content-Location: /new.html
如果目标资源已经存在,并且依照请求中封装的表现形式成功进行了更新,那么,源头服务器必须返回200
(OK
) 或者204
(No Content
) 来表示请求的成功完成。
HTTP/1.1 204 No Content
Content-Location: /existing.html
HTTP状态码
状态码类别
类别 | 原因短语 | |
---|---|---|
1XX | Informational(信息性状态码) | 接受的请求正在处理 |
2XX | Success(成功状态码) | 请求正常处理完毕 |
3XX | Redirection(重定向状态码) | 需要进行附加操作以完成请求 |
4XX | Client Error(客户端错误状态码) | 服务器无法处理请求 |
5XX | Server Error(服务器错误状态码) | 服务器处理请求出错 |
常见状态码(点击展开)
100:表示收到请求消息头,客户端应继续发送主体
200:请求被正常处理
201:PUT请求返回这个状态码,表示请求已成功提交
204:请求被受理但没有资源可以返回
206:客户端只是请求资源的一部分,服务器只对请求的部分资源执行GET方法,相应报文中通过Content-Range指定范围的资源。
301:永久性重定向
302:临时重定向
303:与302状态码有相似功能,只是它希望客户端在请求一个URI的时候,能通过GET方法重定向到另一个URI上
304:发送附带条件的请求时,条件不满足时返回,指示浏览器使用缓存中所请求资源的副本
307:临时重定向,与302类似,只是强制要求使用POST方法
400:请求报文语法有误,服务器无法识别
401:请求需要认证
403:请求的对应资源禁止被访问
404:服务器无法找到对应资源
405:不支持请求中使用的请求方法
413:请求主体过长,服务器无法处理 (探查缓冲区溢出时会有)
414:请求URL过长,服务器无法处理
500:服务器内部错误
503:服务器正忙,用来说明服务器现在无法为请求提供服务,但将来可以 (服务器负载过大)
HTTP请求头
Accept
用来告知(服务器)客户端可以处理的内容类型,这种内容类型用MIME 类型来表示。
展开语法
Accept: text/html
Accept: image/*
Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8
Accept-Charset
用来告知(服务器)客户端可以处理的字符集类型
展开语法
Accept-Charset: iso-8859-1
Accept-Charset: utf-8, iso-8859-1;q=0.5
Accept-Charset: utf-8, iso-8859-1;q=0.5, *;q=0.1
Accept-Encoding
将客户端能够理解的内容编码方式,通常是某种压缩算法,通知给服务端
展开语法
Accept-Encoding: gzip
Accept-Encoding: compress
Accept-Encoding: deflate
Accept-Encoding: br
Accept-Encoding: identity
Accept-Encoding: *
Authorization
请求消息头含有服务器用于验证用户代理身份的凭证,通常会在服务器返回401
Unauthorized
状态码以及WWW-Authenticate
消息头之后在后续请求中发送此消息头。
Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
Connection
决定当前的事务完成后,是否会关闭网络连接。如果该值是“keep-alive”,网络连接就是持久的,不会关闭,使得对同一个服务器的请求可以继续在该连接上完成。
展开语法
Connection: keep-alive
Connection: close
X-Forwarded-For (XFF)
代表最初发起请求的客户端的真实 IP 地址,只有在通过了HTTP代理或者负载均衡服务器时才会添加该项。
如果一个请求经过了多个代理服务器,那么每一个代理服务器在转发请求时,都可以将自己的IP地址添加到X-Forwarded-For
头部中。最右端的 IP 表示最近通过的代理服务器,而最左端的 IP 表示最初发起请求的客户端的 IP 地址。
展开语法
X-Forwarded-For: <client>, <proxy1>, <proxy2>
X-Forwarded-For: 2001:db8:85a3:8d3:1319:8a2e:370:7348
X-Forwarded-For: 47.11.22.33
X-Forwarded-For: 47.11.22.33, 70.41.3.18, 150.172.238.178
更多其它头部
Cache-Control: 缓存的控制
Transfer-Encoding: 报文主体的传输编码方式
Host: 请求资源所在服务器和端口号 Accept: 可处理的媒体类型 Accept-Charset: 可接收的字符集 Accept-Encoding: 可接受的内容编码 Accept-Language: 可接受的自然语言
Cookie: 用于向服务器提交它以前发布的cookie
If-Modified-Since: 用于说明最后一次收到所请求资源的时间,如果自那之后资源没有变化,服务器会返回一个状态码304的响应,指示客户端使用资源的缓存副本
If-None-Match: 用于指定一个实体标签,当最后一次收到所请的求资源时,浏览器提交服务器发布的实体标签,服务器可以使用实体标签,确认浏览器是否使用资源的缓存副本
Origin: 用在Ajax跨域请求中,用于指示提出请求的域
Referer: 指示发出当前请求的原始URL
User-Agent: 提供生成请求客户端软件的有关信息
Allow: 资源可支持的HTTP方法
Location: 在重定向响应中,说明重定向的目标
Server: 提供所使用的Web服务器软件的信息
Accept-Ranges: 可接受的字节范围
Content-Type: 规定消息主体的类型 Content-Encoding: 实体主体适用的编码方式,一些应用程序用它压缩响应加快传输 Content-Language: 实体主体的自然语言 Content-Length: 规定消息主体的字节长度 (HEAD方法例外) Content-Range: 实体主体的位置范围,一般用于发出部分请求时使用
Transfer-Encoding: chunked 分块传输;常用它指定块编码,它是指定HTTP传输对消息主体使用的任何编码的
Access-Control-Allow-Origin: 指示可否通过跨域Ajax请求获取资源
Set-Cookie: 用于向浏览器发布Cookie,浏览器会在随后的请求中将其返回给服务器
WWW-Authenticate: 在带401状态码的响应中,提供与服务器所支持的身份验证类型的有关信息 (如基础认证)
X-Frame-Options: 指示浏览器框架是否加载以及如何加载当前响应
HTTP Cookie
HTTP协议是无状态的,为使用正确的状态数据处理每个请求,常用Cookie对用户会话进行唯一标识。
浏览器会存储 cookie 并在下次向同一服务器再发起请求时携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。
Cookie 一般由一个 名/值 对组成(id=12345),也可以包含任何不含空格的字符串。
除Cookie的实际值外,Set-Cookie消息头还可以包含以下可选属性,用它们控制浏览器处理Cookie的方式。
HTTP头 | 作用 |
---|---|
expires | 用于设定Cookie有效时间,此时间内cookie一直有效(如没有则关闭浏览器失效) |
domain | 用于指定cookie的有效域,这个域必须和收到Cookie的域相同,或是它的父域 |
path | 指定cookie的有效URL路径 |
secure | 如果设置这个属性,则仅在HTTPS请求中提交Cookie |
HTTPOnly | 如果设置这个属性,将无法通过客户端javascript直接访问Cookie |
HTTP 身份验证
HTTP 提供一个用于权限控制和认证的通用框架。最常用的 HTTP 认证方案是 HTTP Basic authentication。
**Basic:**基础认证,使用用户的 ID/密码作为凭证信息,并且使用 base64 算法进行编码。
使用BurpSuite的 Intruder模块自定义迭代器base64编码payload后请求可攻击基础认证。
Tomcat默认的认证方式就是HTTP basic认证,当然常用啊Apache和Nginx也可以设置基础认证。
使用 Apache 限制访问和基本身份验证
要对 Apache 服务器上的目录进行密码保护,你需要一个 .htaccess
和 a .htpasswd
文件。
该 .htaccess
文件格式通常看起来像这样:
AuthType Basic
AuthName "Access to the staging site"
AuthUserFile /path/to/.htpasswd
Require valid-user
该 .htaccess
文件引用一个 .htpasswd
文件,其中每行用冒号(“:”)分隔的用户名和密码。你不能看到真实的密码因为它们是 encrypted (在这个例子中是使用了 MD5). 你可以命名.htpasswd
文件 为你所喜欢的名字,但是应该保证这个文件不被其他人访问。(Apache 通常配置阻止访问 .ht*
类的文件).
aladdin:$apr1$ZjTqBB3f$IF9gdYAGlMrs2fuINjHsz.
user2:$apr1$O04r.y2H$/vEkesPhVInBByJUkXitA/
Nginx 访问限制和基本认证
在 nginx 配置中,对需要保护的 location 你需要做如下配置:auth_basic 指令提供密码保护域的名称;auth_basic_user_file 指令指定包含用户密文的证书的文件(与 apache 例子中一致)
在 nginx 中,你需要指定一个保护区域和该 auth_basic
指令提供的保护区域名字。然后该 auth_basic_user_file
指令指向一个.htpasswd
包含加密用户凭据的文件,就像上面的 apache 例子。
location /status {
auth_basic "Access to the staging site";
auth_basic_user_file .htpasswd;
}
在线生成.htpasswd https://www.sojson.com/htpasswd.html
HTTP代理
当配置浏览器使用代理服务器时,它会将所有的请求提交到代理服务器,代理服务器再将请求转给Web服务器。常用的代理服务器软件有BurpSuite和Fiddler。
如果使用代理服务器,HTTP工作机制会出现两方面差异:
(1) 当使用代理服务器发布HTTP请求时,它会将完整的URL插入请求中,代理服务器将提取主机名和端口,用这些信息将请求指向正确的目标Web服务器
(2) 当使用HTTPS时,浏览器无法与代理服务器进行SSL握手,因为这样会破坏隧道,使通信遭受拦截攻击,因此浏览器必须将代理作为一个纯粹的TCP中继,一直开放TCP连接
HTTP/1.1新特性
一、 默认持久连接,Connection: keep-alive
二、 管线化 ( pipelining ),客户端可以同时发出多个HTTP请求,而不用一个个等待响应
三、 断点续传。实际上就是利用HTTP消息头使用分块传输编码,将实体主体分块传输
利用新特性有两种Bypass WAF(绕过Web应用防火墙)的方法。