您现在的位置是:首页 >其他 >【HTTP协议详解】网站首页其他
【HTTP协议详解】
目录
1.什么是http
HTTP全称为“超文本协议”,是一种十分广泛的应用层协议
Http往往是基于tcp协议实现的.(HTTP1.0,HTTP1.1,HTTP2.0均为tcp实现的,HTTP3.0是基于UDP协议的)。这里我们主要讨论Http1.1版本为主。
例如我们平时打开的一个网页/网站就是通过http协议来传输数据的。
应用层:关注数据怎么使用
传输层:关注的是整个数据传输的起点和终点
网络层:地址管理+链路选择
数据链路层:相邻节点的数据转发
物理层:基础设备,硬件
当我们在浏览器输入一个网址的时候,浏览器就会给服务器发送一个HTTP请求,HTTP服务器就会返回一个Http响应,这个响应被浏览器解析之后就变为我们看到的页面的。
“超文本”就是说传输的不仅仅是文本(html,css这些就是文本)还会传输一些音频,图片等等。
2.抓包工具
2.1 抓包工具
当我们要访问一个网站的时候,可能会涉及不止一个http请求/响应的过程。
那么我们就可以通过抓包工具取看看一看他的过程和报文格式。
我们这里使用fiddler抓包,分析http请求/响应的细节
下载地址:链接: link
地址:https://www.telerik.com/fiddler
打开以后就是下面这个样子.
左侧窗口显示了所有的 HTTP请求/响应, 可以选中某个请求查看详情.
右侧上方显示了 HTTP 请求的报文内容. (切换到 Raw标签页可以看到详细的数据格式)
右侧下方显示了 HTTP 响应的报文内容. (切换到 Raw 标签页可以看到详细的数据格式)
请求和响应的详细数据, 可以通过右下角的 View in Notepad 通过记事本打开.
2.2 抓包原理
当浏览器访问百度的时候,就会把Http请求发给fiddler,然后由fiddler再发给服务器,由服务器会将数据返回到fiddler,再由fiddler将数据返回到浏览器中。
因此,fiddler就相当于一个浏览器和客户端的代理商,对于整个交互的数据细节都十分清楚。
3.Http协议格式
HTTP的格式分为两个,分别是请求和响应。
3.1Http请求报文
这个就是我们发送请求是报文格式
请求格式:
首行:方法 URL 版本号
header:请求的属性, 冒号分割的键值对;每组属性之间使用 分隔;遇到空行表示Header部分
结束
空行:作为header的结束标志
body:(有的时候可以没有)空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度;
3.2Http响应报文的格式
这个就是我们响应的内容了,同样分为四部分
响应格式
首行:版本号 状态码 状态码描述
header:请求的属性, 冒号分割的键值对;每组属性之间使用 分隔;遇到空行表示Header部分
结束
空行:作为header的结束标志
body:此处是正文(这里是html代码),Http响应要的就是这个html本体,浏览器拿到这个就会解析成页面展示出来。
4.请求报文格式
4.1 报文首行
首行:方法+URL+版本号
方法最常用的是以下的几个,其中最常用的是get和post方法,另外head和delete有时候也会出现。
使用方法如下:我们继承父类HttpServlet,并且重写其中的doGet和doPost方法
Get是HTTP中最常用的方法,用于获取服务器上的某个资源,当我们在浏览器输入一个URL,浏览器就会像服务器发送一个Get请求
Post方法就是往服务器中提交数据,例如登入的时候/上传文件的时候
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/lianxi")
public class lianxi extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//super.doPost(req, resp);
}
}
get和Post,表示的是不同的语义,但是实际上也并非需要严格遵守
Http的方法语义,只是一种建议,程序员使用的时候不一定要遵守
get中也有可能会出现body,非常少见,post中也可以没有body,比较少见
get和Post的区别
本质上是没有区别的,只是使用习惯上的不同
1.get习惯上表示获取一个数据,post表示提交一个数据
2.get一般没有body,需要携带的数据存在URL中的qurey String中,post一般有body
3.get一般会设计成幂等的,post则无需这样(什么是幂等?就是如果输入的一定那么输出也一定,这就是幂等)
4.get可缓存的(前提是幂等下)post则不能
5.get请求可以被浏览器收藏,post则不能t
URL 唯一资源定位符 描述了网络上唯一的一个资源
主要就是:协议方案名+服务器地址+端口号(不写的话就是默认)+带层次的路径+查询字符串
带层次的路径:标识要访问的这个服务器资源是啥
字符串也就是qurey sting 使用键值对结构,使用&分割键值对,使用=分割键和值
版本号,最常用的是HTTP1.1 这个也是最主流的版本,大多数浏览器上的网站都是1.1
4.2 请求报文header
大家看请求报文中的header格式
每一行就是一个键值对**,键和值之间用:来隔离**
同时以空行作为header的结束标志
Host属性
这个属性就是描述浏览器要访问那个服务器是谁,不仅仅可以写地址还可以有端口号
其实在URL中我们已经写了要访问的服务器是谁。这里又写了一遍这是为啥呢?
大多数情况下,URL和Host的地址是一样的,但是当我们要访问的服务器不是直接访问而是通过代理来访问,那么这两个地址就不一样了。
Host表示的是最终地址,URL表示的是当前地址
Content-type Content-length 属性
Content-type 描述了数据的类型
Content-length 描述了数据的长度
这个两个属性根body相关联如果是没有body的get方法,那么就没有这两个属性
这个表示的是一个html页面,但是最常见还是下面这个类型的
application/json标识数据的类型,是以json格式的
在进行前后端的交互的时候,json是最常见的一个数据格式
json格式用{ }来表示,里面包含多个键值对,键和值之间用“ :”分割,键值对之间用“ , ”来分割
此外Content-type还有其他的写法
application/x-www-from-urlencoded (form表单提交数据的时候,会生成这种body)
此时的body数据就跟query string样式是一样
username=tz&passsword=123&uuid=xxxx
User-Agent属性
User-Agent简称UA,描述了浏览器什么版本,电脑系统是啥版本
Referer属性
referer属性主要是描述当前页面是从哪个页面跳转来的,如果是在地址栏直接输入一个地址,此时请求中没有referer。
Cookie属性
cookie属性也是键值对,键值之间使用“ ; ”来分割,键和值之间使用“ =”来分割
这里面啥意思我们也不知道,这个是程序员自定义的
cookie本质是浏览器本地存储用户自定义的一种关键机制
同一个网站共享一个cookie
不同网站,则是各自的cookie
Cookie从哪里来?
从服务器来的,当我们的浏览器访问服务器的时候,服务器就会在HTTP中响应,通过Set-Cookie把cookie的键值对返回给浏览器,浏览器收到这个数据,就会进行本地存储。
Cookie到哪里去?
在下一次请求的时候,把cookie带给服务器,cookie在浏览器只能算是寄存的。还是需要服务器来使用。
Cookie有啥用?
是浏览器本地存储的数据机制,任何数据都行,前提是字符串
最典型的应用:就是存储用户的身份信息
在Http中遇到的键值对
1.url中的query String
2.header中的每一行是一个键值对
3.body部分,如果Content-type是application/x-www-from-urlencoded 或者json,body的内容就是键值对
4.cookie里面存储的数据就是键值对
5. 响应报文格式
首行:版本号+ 状态码 +状态码描述
版本号根请求的是一样的。
状态码:用数字描述这次请求是成功还是失败,原因是什么
状态码描述:通过一个或一组单词,表示状态码含义
如下图
给大家列举几个最常用的:
200 ok表示请求成功
404 NOT Found 表示要访问的资源不存在
403 Forbidden 访问被拒绝(没有权限)
500 Internal Server Error 服务器内部错误
504 Gateway Timeout 服务器请求超时了(服务器没有返回响应)
重定向?就是访问旧的的地址,被自动引导到新的地址上了
302 Move temporarily 临时重定向
301 Moved Permanently 永久重定向
至于header和body和请求的是一样的,这里就不多说了。
Content-Type
响应中的 Content-Type 常见取值有以下几种:
text/html : body 数据格式是 HTML
text/css : body 数据格式是 CSS
application/javascript : body 数据格式是 JavaScript
application/json : body 数据格式是 JSON
6.构造Http请求
1.直接在地址栏输入一个URL
2 .在html中一些特殊的标签也可以触发get请求
3.通过form表单,可以触发get和post请求
当我们点击提交的时候,就会触发一个get请求,URL中的query string 中就会出现aaa=111&bbb=222字符串,nama相当于键,aaa和bbb就相当于我们输入的值。
form只支持get 和post。对于其他的delete options方法并不支持
使用form的话默认版本号位HTTP1.
4.ajax【重要】
这个是现在最主流的前后端交互方式之一
全称为 Asynchronous Javascript And XML(Asynchronous 异步)
这里我们使用jquery里面提供的ajax api
$ 在jquery中是一个特殊的全局变量,jquery中的各种api都是$的方法
$也是变量名的一部分
这两个代码就是通过ajax来构造get和post请求。
<script>
$.ajax({
type:'get',
url:'https://www.baidu.com?studentName=zhangsan',
data:"这个是body",
// 回调函数 ,当服务器返回的响应到达浏览器的时候产生回调
// 此处的回调体现了’异步‘
success:function(data)
{
// data则是响应的正文部分
console.log("当服务器返回的响应到达浏览器的时候,浏览器会触发该回调,通知到我们的代码中");
}
});
console.log("浏览器立即执行往后的代码");
</script>
<script>
$.ajax({
type:'post',
url:'https://www.baidu.com',
data:"这个是body",
// 回调函数 ,当服务器返回的响应到达浏览器的时候产生回调
// 此处的回调体现了’异步‘
contentType:"text/html",
success:function(data)
{
// data则是响应的正文部分
console.log("body");
}
});
</script>
Postman
我们还可以通过postman来就行构造HTTP方法
7.Https协议
Https也是一个应用层的协议,是在Http协议的基础上引入一个加密层
因为Http协议传输内容都是明文传输的,这个就导致了不可靠性。
比如:我们要下载一个“天天音乐”,但是由于是Http传输的,不安全,就会导致被篡改了内容,让我们下载的内容变为“QQ音乐”。
7.1 对称密钥
对称加密:只有一个密钥
加密=》明文+密钥=》密文
解密=》密文+密钥=》明文
加密和解密使用的是同一个密钥
优点:计算快速
加密:针对的是HTTP中的header和body部分
使用对称密钥:
优点
既然客户端需要自己生成一个密钥,那么服务器怎么知道呢?
如果通过网络传输没有加密,黑客就会获取,所以我们也需要对密钥进行一个加密
因此我们引入了“非对称密钥”
7.2 非对称密钥
非对称密钥
需要两个密钥,一个公钥(pub)一个私钥(pri)
明文+pub=》密文&& 密文+pri=》明文
或者
明文+pri=》密文&& 密文+pub=》明文
客户端想要黑客拿不到对称密钥
所以我们需要服务器生成一对非对称密钥(公钥和私钥)
客户端和服务器的数据传输还是以对称加密的方式进行的(速度快,成本低)
为了保证对称密钥安全的到达服务器,使用非对称密钥进行加密,保护对称密钥
非对称密钥在保护完对称密钥以后,就可以不用了。
公钥和私钥就是两个比较大得数,谁当公钥都行,这里约定,公布出来的是公钥,自己留的是私钥。
大家需要注意,这里一共是有三把密钥,一对非对称密钥,和一个对称密钥
因为这个时候,黑客就不知道私钥是什么,所以黑客就没办法解密,这个时候就是安全的。
7.3 证书
但是如果这个时候:
这个黑客此时,黑客自己生成了一对非对称密钥pri2和pub2,
黑客把自己的公钥pub2传给客户端,那么客户端就会以黑客的【pub2】进行密钥key的密文传输,同时,黑客把公钥给记住~~黑客就可以使用自己的 pri2针对密文解密,拿到了key !!
黑客继续用服务器的pub 对key重新加密,把密文发给服务器!!
这个样子的话依然还是不安全,因此我们就需要引入一个“证书”来帮助我们,判断黑客是否篡改了我们的信息。
这个 证书 可以理解成是一个结构化的字符串, 里面包含了以下信息:
证书发布机构
证书有效期
公钥
证书所有者
签名
…
当客户端获取到这个证书之后, 会对证书进行校验(防止证书是伪造的).
这个证书是由一个权威机构发布的,也有一个公钥和私钥(pub2,pri2)。
客户端拿到证书之后,就首先需要针对证书进行校验!!!
1.得到初始的签名:客户端使用系统中内置的权威机构的公钥pub2,针对上述证书中的加密签名进行解密.得到了初始签名(这个签名是权威机构算出来的)(设为sum1)
⒉计算现在的签名:客户端使用同样的签名计算算法,基于证书中的属性重新计算,得到sum2.比较两个签名是否相同~~如果相同,说明证书中的数据都是未被篡改的原始数据!!
如果签名不同,说明证书的数据被篡改过,客户端的浏览器弹框报错!