作者:~小明学编程
文章专栏:JavaEE
格言:热爱编程的,终将被编程所厚爱。
目录
什么是HTTP协议?
HTTP (全称为 "超文本传输协议") 是一种应用非常广泛的应用层协议,HTTP是一种设计好的协议格式,其可扩展的能力比较强,我们可以根据自身的需要去传输各种格式的数据。
其中我们的HTTP协议往往是基于传输层的TCP协议来实现的(HTTP1.0, HTTP1.1, HTTP2.0 均为TCP, HTTP3 基于 UDP实现) 我们接下来的介绍主要都是1.1版本的。
通常情况下我们打开一个网站就是通过 HTTP 协议来传输数据的,当我们在浏览器中输入一个 搜狗搜索的 "网址" (URL) 时, 浏览器就给搜狗的服务器发送了一个 HTTP 请求, 搜狗的服务器返回了一个 HTTP 响应。
抓包工具
所谓的抓包工具相当于一个代理,我们在访问一个网站的时候首先会把HTTP的请求发送给代理,然后代理会将请求转发给服务器,这时服务器会返回一个响应,这个响应先到我们的代理的手中,然后代理再转发给浏览器,浏览器再对数据进行解析将数据呈现给我们的用户。
这个代理就是我们的抓包工具,这里我们介绍fiddler的使用。
fiddler的下载地址:https://www.telerik.com/fiddler/
其中下载安装的一些细节这里就不多说了,大家可以自行百度或者去B站或者抖音搜索。
抓包工具的使用
当我们打开我们的浏览器进入到搜狗的官网,然后就发现我们这边抓取到了很多的信息,其中大部分是HTTPS协议的(HTTPS相比HTTP的主要区别是HTTPS就信息进行了加密使得我们的信息在传输的时候不容易被更改)
接下来我们打开一个响应,一般情况下我们都会选择raw原始的请求和响应进行查看
可以看到这里传输了一个前端的页面,同时我们在进行交互的时候传输的不止一个http的请求和响应会有多个请求和响应是同时进行的。
协议的格式
在我们抓到包之后就该了解我们HTTP的协议格式到底是怎么样的了
请求部分
我们的请求主要包括四个部分:
1.请求行:
1)HTTP的方法,其中常用的就是GRT和POST这两种方法,描述了我们想要干什么。
2)URL:描述了我们的资源在哪里。
3)版本号:就是我们当前的HTTP协议的版本号也就是上面的 HTTP/1.1,表示我们用的是1.1版本。
2.请求头:
1)每一行都是一个键值对,键和值之间使用 :空格 来分割。
2)键值对的个数不固定,不同的键值对表示不同的含义。
3.空行:
请求的结束标志。
4.请求正文:
body部分有些请求有,有些没有。
响应部分
响应同样主要包含了四个部分:
1.首行:
1)HTTP/1.1:和我们前面描述的一样是版本号。
2)200:是我们的一个状态码,描述了这个响应的一个状态,是成功了还是失败了。
3)OK: 对我们的状态码的一个简单的解释。
2.响应头:
也是键值对结构,每个键值对占一行,每个键值对之间使用 : 和 空格 来分割。响应头当中的键值对个数,也是不确定的,不同的键值对表示不同的含义。
3.空行:
表示响应头的结束。
4.响应正文:
就是服务器返回给客户端的具体数据。内容可能有各种格式,最常见的就是 HTML。
详解请求
URL
平时我们俗称的 "网址" 其实就是说的 URL (Uniform Resource Locator 统一资源定位符)。
互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
其基本的格式如下:
协议方案名:就是我们的协议名称分为http和https这两种。
登录信息:就是我们的用户的登录信息,现在一般没有了。
服务器地址:可以是我们的IP地址也可以是域名,一般情况下都是域名,帮助我们找到我们资源所在网络的位置。
服务器端口号:在我们到达服务器的地址之后就需要从该服务器中找到指定的位置访问的哪一个程序,大部分情况下,端口号都是会省略的。省略的时候,浏览器会自动加一个端口号。
带层次的文件路径:描述了当前想要访问的服务器的资源是啥。
通过这些 IP 地址,端口,带层次的文件路径,就描述了一个网络上具体的资源。
查询字符串:本质上是 浏览器/客户端 给服务器传送的自定义信息,相当于对获取到的资源提出了进一步的要求。
片段标识符:描述了要访问当前 HTML 页面中哪个具体的子部分,能够克制浏览器滚动到相关的位置。
URL的encode和decode:
当 query string 中如果包含了特殊字符,就需要对特殊字符进行转义。转义的过程就叫做 URLencode,反之,把转义后的内容还原回来,就叫做URLdecode。
因为一个 URL 里面是有很多特殊的含义的符号的:/ : ? & = …这些符号都是在 URL中具有特定含义的。万一,queryString 里面也包含这类特殊符号,就可能导致 URL 被解析失败!所以要进行 encode。
我们看到这两个+号就被转义了。
方法
我们可以看到方法有很多种但是我们常用的就只有get和post这两种。
get和post的区别
get和post并没有本质上的区别,也就是说get的使用场景我们post也可以用,get的使用场景post也可以用,但是从细节上来看也可以区分一些不一样的地方。
1.一般情况下get用于获取数据而post用来上传数据。
2.一般情况下get是没有body的,get是通过 query string 向服务器传递数据的,而post一般是有body的,通过body向服务器传递数据。
3.一般情况下get是幂等的,也就是相同的输入我们得到的输出结果是确定的,而post一般是不幂等的,也就是相同的输入我们所得到的输出结果是不确定的。
4.get通常情况下可以被缓存,而post一般不能被缓存。
请求报头
Host
表示服务器主机的地址和端口,例如:Host: www.baidu.com
Content-Length
表示body中的数据长度,HTTP 也是基于 TCP 协议的,TCP 是面向字节流,有粘包问题,所以这里也有,就可以通过下面这两种方法来解决,使用分隔符或者用长度
Content-Type
表示请求中body中的数据格式。
User-Agent
这里表示的是,当前用户是拿一个什么样的东西来上网。我们找一个 fiddle 里面的包来看:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76
这里就描述了我的当前的一个设备,现在主要用于区分手机端还是PC端。
Referer
参考,表示我们当前的网址是由哪一个网址跳转而来的
Referer: https://www.baidu.com/
Cookie
Cookie 中存储了一个字符串, 这个数据可能是客户端(网页)自行通过 JS 写入的, 也可能来自于服务器(服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回数据).
往往可以通过这个字段实现 "身份标识" 的功能。
也就是说我们专门划分出来一块区域用于存储我们的验证信息,例如我们登录一个网站如CSDN然后我们首先要输入账号密码,这个时候我们把账号密码给发送到服务端,然后服务端会返回给我们一个Cookie,接着储存在本地,然后我们每次访问其它的页面的时候就会有这个身份标识不用每一个页面都输入一次密码。
通过一个一个的键值对来表示。
Session
Session的作用相当于是记录我们的会话我们做了啥都会记录在内。
响应详解
状态码
http的状态码有很多种,下面我们介绍几种最常见的:
200:就是表示浏览器很顺利的就获取到了想要的内容了,没有出现意外。
404:这个我们应该很常见,表示的意思是你访问的资源不存在,例如你在网址栏里面随便输入一个网址大概率就是404.
403:表示你访问的资源存在但是你没有访问权限。
405:访问的方式不允许,比如用 GET 访问只支持 POST 的服务器。
500:就是指服务器出现了 bug。
504:表示服务器很繁忙。
302:表示重定向。
报头
响应报头的格式和请求报头的格式基本一致。像 Content-Type , Content-Length 等属性的含义也和请求中的含义一致。不过响应的 Content-Type 常见取值有这几种:
- text/html : body 数据格式是 HTML
- text/css : body 数据格式是 CSS
- application/javascript : body 数据格式是 JavaScript
- application/json : body 数据格式是 JSON
模拟构造HTTP请求
构造http请求常见有两种方法:
1.基于HTML/JS:
1)基于form表单
2)基于Ajax
2.基于Java中的socket
基于form表单构造请求
核心 HTML 标签,就是 form 标签。form 标签里面的 action,就是提交请求的地址是什么。还有就是 method 就是由 GET 请求来提交,还是 POST 请求来提交然后还需要搭配 from 里面的一些其他标签,比如 input 之类的。
<form action="https://www.sogou.com/" method="get">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="提交">
</form>
form 是最原始的构造方式,使用 form 一定会跳转页面,会加载全新页面,就会有很大的资源消耗。如果只加载一部分变化的内容,就需要用到 Ajax 了。
基于 Ajax 构造 HTTP 请求
Ajax 就是通过 JS 代码,来构造 HTTP 请求,再通过 JS 代码来处理这里的响应,并且把得到的一些数据更新到页面上面。全名是:Asynchronous Javascript And XML
,就是:异步 JavaScript 和 XML。
Ajax 就是先构造出一个 HTTP 请求发给服务器,然后就执行其他代码,等到服务器的响应回来了,再去执行。
通过 JQuery 来实现 Ajax 请求:关于JQuery的使用大家自行参考网络上的方法。
<script src="jquery.js"></script>
<script>
$.ajax({
type: 'get',
url: 'https://www.sogou.com/index.html',
success: function(body) {
// success对应一个回调函数其参数就是http响应的body部分
console.log("获取到响应的数据"+body);
},
error: function() {
console.log('获取响应失败');
}
})
</script>
Ajax 的参数只有一个,是一个对象,里面有 type,就是访问类型。url 就是访问地址。success 就是回调函数,服务器返回信息之后,就执行。error 就是获取相应失败执行:
这里我们发现报错了,报错的原因是我们出现了跨域访问。
跨域访问:跨域访问,是指从一个域名的网页去请求另一个域名的资源。比如从 www.baidu.com 页面去请求 ww w.google.com 的资源。
但是一般情况下不能这么做跨域访问,因为有浏览器的 “ 同源策略 ” 存在,这是浏览器对 JavaScript 施加的安全限制。
HTTPS
HTTPS 也是一个应用层协议. 是在 HTTP 协议的基础上引入了一个加密层.
HTTP 协议内容都是按照文本的方式明文传输的. 这就导致在传输过程中出现一些被篡改的情况。
至于为什么要引用HTTPS那就不得不说一下万恶之源 “运营商劫持” 了。
由于我们通过网络传输的任何的数据包都会经过运营商的网络设备(路由器, 交换机等), 那么运营商的网络设备就可以解析出你传输的数据内容, 并进行篡改,在早期的时候想必大家基本都遇到过这种情况,也就是我们想要下载一个游戏或者软件直接从百度上搜索的话,我们下载完毕的时候发现下载的是另外一个软件,这就是中间的时候被劫持了,然后把关键的下载地址改了。
想要解决这个问题我们就得对其进行加密,让别人无法对中间的过程进行更改。
HTTPS的工作原理
既然我们的数据会被劫持那么我们就对齐进行加密,加密分为两种分别是对称加密和非对称加密,下面我们就来简单的介绍一下这两种加密方式:
对称加密
所谓的对称加密就是我们在传输数据之前对数据进行加密,当服务端拿到数据之后再对数据进行一个解密。
简单的描述一下这个过程就是上述,这时就算黑客截取到了中间的密文,因为没有密钥也是没有什么用的。
但是这样的方式也有一个致命的缺陷,那就是我们双方都要有相同的密钥,要想保证密钥的相同那就得传输密钥,但是在传输的过程中密钥可能会被劫持,这样黑客就又能得到数据了,想要解决这个问题就需要我们的非对称加密了,需要对我们所传输的密钥再次进行加密。
非对称加密
非对称加密中我们会引入公钥和私钥,我们的服务器生成一对公钥和私钥,其中我们把公钥发给我们的客户端,用于加密,然后我们再用我们的私钥对返回的数据进行解密。
这个过程就算黑客从中截取到了公钥也没有用,没有私钥解不开,或者解开的成本非常的大。
但是这中间还是会产生问题,就是我们的黑客在中间截取到我们服务器的公钥,然后伪造另外的假的公钥发给客户端,客户端拿到公钥对密文加密发送给服务端,中间黑客再次截取并且用自己的私钥解开然后再用刚刚截取到的公钥加密再次发给服务端这样就得到了我们的密文了。
想要解决这个问题我们就得引用第三方的公信部门,对我们发送的数据进行一个验证是不是合法的公钥。
关于HTTP就先讲到这里,有帮助的可以给个👍。