1.HTTP概述
1.1什么是HTTP
HTTP/HTTPS是一种应用层的协议,应用层协议很多时候都是程序员自己定制的,需要根据具体的场景来制定应用层协议,但是由于程序员水平参差不齐,大佬设计的协议很好用,菜鸟设计的协议一言难尽,于是有一些大佬就发明了很好用的协议,直接让大家照搬,HTTP就是其中的一个典型代表,HTTP虽然已经设计好了,但是它的扩展性极强,可以根据需要让程序员自定义数据信息。
HTTP是一种超文本传输协议,是互联网上应用最为广泛的一种网络协议。那如何才能看到HTTP的报文格式或信息,这就需要对HTTP进行抓包,下面介绍一下如何进行HTTP的抓包。
1.2抓包工具Fidder的使用
Fidder是一款专门抓HTTP/HTTPS包的软件,它的原理就是充当一个代理,比如当访问一个网站时,会先将请求发送给Fidder,然后Fidder再把请求发送给目标网页的服务器,同理服务器返回的响应也一样,先需要经过Fidder,再发送给客户端。
这样,Fidder就能够捕获到HTTP的请求与响应,由于Fidder充当的是一个“代理”的角色,所以使用Fiddder时不能够有其他使用或修改代理的软件运行,否则Fidder就不能够捕获到HTTP/HTTPS的包。
1.2.1下载
下载很简单,直接去官网下载即可,网址为www.telerik.com/fiddler。
首先直接打开网页是下面这个样子的。
进入官网后,我们往下翻,找到如图的页面,Fidder Classic,这个是免费的。
点击Try to Free。
点击后,会跳转到如下的页面。
填写信息,下载即可。
1.2.2安装
至于安装,就非常简单了,一路next就可以了。
安装过后,需要设置一下,首先现在的大部分网页都是HTTPS格式的,所以需要设置HTTPS的捕捉。
第一步,找到Tools选项,选择Options,找到HTTPS。
将如图的选项全部勾上,并确定。
然后,会有一个窗口跳出来,一定要点yes,不然就要重装Fidder了,这样Fidder就可以使用了。
如果Fidder一直报The system proxy was changed,click to reenable fiddler capture,这样的警告,这种情况大概率是存在冲突的软件,代理被修改了,参考一位大佬的博客可以解决:blog.csdn.net/legend818/a…
1.2.3如何使用
Fidder左侧是捕获到的HTTP(s)包,双击某个包后,会在右侧显示详细信息。
显示详细信息后,使用Raw模式可以看到http的本体。
点击View in Notepad可以使用记事本打开,查看详情。
对于右侧的上下两栏,上面是请求,下面是对应的响应。
我们发现响应里面的内容有一串乱码,这可能是压缩或者加密了,可以点击下面黄色的按钮来显示服务器的响应结果。
点击之后:
Fidder的基本使用差不多就是这些。
1.3URI与URL
URI即网络资源标识符,URL即网络资源定位符,前者是使用唯一字符串来标识互联网中某一资源,后者使用字符串来表示某个资源的位置,URL可以理解为URI的一种实现,就像接口与实现类的关系一样。
URL(I)格式:
协议方案名:必选项,使用 http 或https等协议方案名获取访问资源时要指定协议类型。不区分字母大小写,最后附一个冒号:,使用//与后面的字段分隔。 也可使用 jdbc:mysql:// 或 javascript: //这类jdbc程序或脚本程序的方案名。
登录信息:可选项,这是上古时期上网的时候,在这里会体现出账号与密码,现在基本上没有了,使用@符号与后面的字段分隔。
服务器地址:必选项,可以使用域名和IP地址来表示,使用:与端口号分隔,没有端口号:省略。
端口号:可选项,表示访问主机上哪一个应用程序,该字段为空,浏览器会分配默认的端口号,http是80,https是443。
文件路径:必选项,描述访问服务器的资源是什么,最简单的路径就是一个/,你访问很多网站的首页的时候,最后都会有一个/,使用?与查询字符串分隔。
查询字符串:可选项,表示浏览器或者客户端传给服务器自定义的信息,对获取的资源提出进一步的要求,一般是程序员自定义,所以如果不是你自己写的,大概率看不懂,使用#与片段标识符分隔。
片段标识符:可选项,表示访问页面的子位置,能够控制浏览器滚动到某一位置。
HTTP 协议使用 URI 定位互联网上的资源。正是因为 URI 的特定功能,在互联网上任意位置的资源都能访问到。
1.4URL encode/decode
如果查询字符串(query string)的内容包含一些具有特定含义的字符需要进行转义,如/,?,&等,如果含有这些字符,会将这些字符替换为%字符的ASCII码,这个过程就是encode,反过来将这些转义的字符串解析为原来的字符,这个过程就是decode。
比如,你在浏览器上搜索C++,在URL上就会得到C%2B%2B这样的字符串。
2.HTTP协议格式
2.1HTTP请求格式
2.1.1基本格式
http请求格式包括请求行,请求报头和请求正文,报头与正文之间使用空行做标记进行分隔。 例如,下面的一大段http请求报文。
请求行由三部分构成,分别是方法, URL, HTTP版本号。 方法用来描述请求的目的是什么,比如get方法一般用来获取服务器的资源。 URL表示想要访问的网络资源的位置。 常见HTTP版本号有HTTP/1.0,HTTP/1.1,HTTP/2.0这些都是基于TCP,最新版本的HTTP/3.0是基于UDP。
请求头部,包含很多行,有许多的键值对组成,键和值之间使用:来进行分割,至于键值对的数量,是不固定的。
请求正文是可选项,不一定会有,像上面的那个例子请求正文就是空的。
2.1.2方法
请求行里面的方法完整地说应该叫做告知服务器意图的 HTTP 方法,这里的方法与java里面的方法不同,引入这些方法的初衷就是为了表示不同的语义,比如GET表示获取资源,POST表示上传资源,但是大多数人写代码就是GET/POST一把梭,基本上就没有考虑各种方法的语义。
在http/1.1版本中,最常使用的方法有GET,POST,还有其他方法,引谢灵运的话来说,GET占八斗,POST占一斗,其他方法分剩下的一斗。
各方法功能如下:
GET :获取资源 GET 方法用来请求访问已被 URL 识别的资源。指定的资源经服务器端解析后返回响应内容。也就是说,如果请求的资源是文本,那就保持原样返回;如果是像 CGI(CommonGateway Interface,通用网关接口)那样的程序,则返回经过执行后的输出结果。
POST:传输实体主体 虽然用 GET 方法也可以传输实体的主体,但一般不用 GET 方法进行传输,而是用 POST方法。虽说 POST 的功能与 GET 很相似,但 POST 的主要目的并不是获取响应的主体内容。
PUT:传输文件 PUT 方法用来传输文件。就像 FTP 协议的文件上传一样,要求在请求报文的主体中包含文 件内容,然后保存到请求 URI 指定的位置。 该方法在HTTP/1.1无验证机制,不安全,配合验证机制可以开放使用该方法。
HEAD:获得报文首部 与GET的区别就是HEAD只返回报文的首部。
DELETE:删除文件 DELETE 方法按请求 URI 删除指定的资源,不安全,需配合验证机制使用。
OPTIONS:询问支持的方法 询问服务器支持哪些方法。
TRACE:追踪路径 TRACE 方法是让 Web 服务器端将之前的请求通信环回给客户端的方法,不常用。
CONNECT:要求用隧道协议连接代理 CONNECT 方法要求在与代理服务器通信时建立隧道,实现用隧道协议进行 TCP 通信。主要使用 SSL(Secure Sockets Layer,安全套接层)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加 密后经网络隧道传输。
格式与其他的方法不同:
CONNECT 代理服务器名:端口号 HTTP版本
复制代码
GET方法可以代替POST方法的使用,POST方法也可以替代GET方法的使用,那GET与POST有什么区别?
答:GET与POST没有本质区别,但存在细节差别。 从语义上来说,GET一般用来获取资源,POST一般用来上传资源,不是强制要求,只是建议。 从习惯上说,通常情况下,GET没有body(请求正文),GET通过query string(查询字符串)传输数据。通常情况下,POST有body,POST通过body来传输数据,这也不是绝对的,只是一种习惯。 其他方面,GET请求一般是幂等的,POST请求一般不幂等,幂等的意思是,你每次输入相同的请求得到的输出的结果是确定的,反之不幂等就是输出的结果是不确定的,因为相同结果得到的输出结果相同,那么这个结果是可以被缓存的,否则就不能被缓存,也就是说GET可以缓存,POST不可以缓存,能不能缓存是与幂等是有关系的。
2.2HTTP响应格式
2.2.1基本格式
HTTP响应格式包括响应行,响应头部,响应正文,头部与正文之间使用空行进行分割。
例如下面的这一段响应报文。
响应行包括协议版本,状态码,状态码描述三部分组成。
状态码表示响应的状态是怎么样的,200表示成功,400,500表示失败,状态码描述就是说明对应状态码的意思是什么。
响应头部,分隔符,响应正文在格式上与请求是一样的,其中响应正文最常见的格式就是HTML。
2.2.2状态码
状态码的职责是当客户端向服务器端发送请求时,描述返回的请求结果。借助状态码,用户可以知道服务器端是正常处理了请求,还是出现了错误。
状态码的大类类别:
状态码个大类下的细分表:
状态码与状态信息 | 该状态下的情况 |
200 OK | 表示从客户端发来的请求在服务器端被正常处理了。 |
204 No Content | 该状态码代表服务器接收的请求已成功处理,但在返回的响应报文中不含实体的主体部分。另外,也不允许返回任何实体的主体。 |
206 Partial Content | 该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的 GET 请求。响应报文中包含由 Content-Range 指定范围的实体内容。 |
301 Moved Permanently | 永久性重定向。该状态码表示请求的资源已被分配了新的 URI,以后应使用资源现在所指的 URI。 |
302 Found | 临时性重定向。该状态码表示请求的资源已被分配了新的 URI,希望用户(本次)能使用新的 URI 访问。 |
303 See Other | 该状态码表示由于请求对应的资源存在着另一个 URI,应使用 GET方法定向获取请求的资源。 |
304 Not Modified | 该状态码表示客户端发送附带条件的请求时,服务器端允许请求访问资源,但没有满足请求条件的资源的情况。 |
307 Temporary Redirect | 临时重定向。该状态码与 302 Found 有着相同的含义。尽管 302 标准禁止 POST 变换成 GET,但实际使用时大家并不遵守。307 会遵照浏览器标准,不会从 POST 变成 GET。但是,对于处理响应时的行为,每种浏览器有可能出现不同的情况。 |
400 Bad Request | 该状态码表示请求报文中存在语法错误。 |
401 Unauthorized | 该状态码表示发送的请求需要有通过 HTTP 认证(BASIC 认证、DIGEST 认证)的认证信息。另外若之前已进行过 1 次请求,则表示用户认证失败。返回含有 401 的响应必须包含一个适用于被请求资源的 WWW-Authenticate 首部用以质询(challenge)用户信息。当浏览器初次接收到 401 响应,会弹出认证用的对话窗口。 |
403 Forbidden | 该状态码表明对请求资源的访问被服务器拒绝了。 |
404 Not Found | 该状态码表明服务器上无法找到请求的资源。除此之外,也可以在服务器端拒绝请求且不想说明理由时使用。 |
500 Internal Server Error | 该状态码表明服务器端在执行请求时发生了错误。也有可能是 Web应用存在的 bug 或某些临时的故障。 |
503 Service Unavailable | 该状态码表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。 |
418 I'm a teapot | 这个是http的一个彩蛋,增加乐趣,其实没什么用 |
2.3首部字段
2.3.1分类
HTTP 首部字段根据实际用途被分为以下 4 种类型。
- 通用首部字段(General Header Fields)请求报文和响应报文两方都会使用的首部。
- 请求首部字段(Request Header Fields)从客户端向服务器端发送请求报文时使用的首部。补充了请求的附加内容、客户端信息、响应内容相关优先级等信息。
- 响应首部字段(Response Header Fields)从服务器端向客户端返回响应报文时使用的首部。补充了响应的附加内容,也会要求客户端附加额外的内容信息。
- 实体首部字段(Entity Header Fields)针对请求报文和响应报文的实体(正文)部分使用的首部,补充了资源内容更新时间等与实体有关的信息。
2.3.2实体首部字段
常用的几个字段: Content-Length,计算body部分的长度,可以配合分隔符解决粘包问题。 Content-Type,表示body中的数据格式。
2.3.3请求首部字段
常用字段: User-Agent,表示客户端是使用什么来进行上网,操作系统信息+浏览器信息。
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
复制代码
Referer,表示当前的页面是从哪一个页面跳转过来的,但是不一定有,如直接输入网址,那就没有原来的那个跳转页面。
2.3.4响应首部字段
2.3.5通用首部字段
2.3.6Cookie
因为HTTP是一种无状态的协议,它无法对之前的发生过的请求和响应状态进行记忆,如果遇到需要登录的页面,登录之后,再刷新,是需要重新进行登录的,这个就非常的难受,为了解决这个问题,引入了Cookie机制。
但是也有好处,可以减少服务器的 CPU 及内存资源的消耗。
Cookie是浏览器为页面提供的一种持久化储存数据的机制,即就是将数据存储磁盘上,不会因为浏览器或者电脑重启而导致数据丢失。
Cookie会按照域名来进行分类并组织,针对每一个域名,都会分配一个“小房间”(一块独立的储存空间),这些小房间之间是相互独立的,在每个“小房间”里面会按照键值对的方式储存数据(值),每个键值对之间使用&来进行分隔。
那Cookie的数据从哪里来?其实是从服务器返回给客户端的,服务器完成客户端的身份认证之后会通过的头部字段Set-Cookie来给客户端响应信息。
就像下面服务器返回的Cookie一样:
Cookie的作用其实就像医院里面的就诊卡一样,就诊卡里面有就诊人的基本信息,刷卡之后会根据这些基本信息可以查出在当前医院里面的历史就诊记录等更加详细的信息,这张就诊卡就相当于Cookie,而根据就诊卡信息获得的详细记录叫做session,每个session里面记录了就诊用户的许多关键信息,例如历史就诊记录,要做的检测等等,每一个session都有对应的sessionId,即会话标识,服务器返回给客户端的Cookie响应就有这个会话标识,然后访问后续页面的,根据这个会话标识就能从服务器找到对应的信息进行登录,这样刷新页面就不用在重复登录了。