1. HTTP是什么
HTTP (全称为 "超文本传输协议") 是一种应用非常广泛的应用层协议.
HTTP是文本协议.
IP,TCP,UDP是二进制协议.
HTTPS加密之后是二进制.
使用浏览器,打开网站,这个过程都是HTTP来支持的.
- "超文本"的含义:
文本=>字符串
超文本=>除了能够传输字符串,还能传输其它的.图片,字体,视频,音频.
- HTTP响应:
当在浏览器中输入一个搜狗搜索的 "网址" (URL) 时, 浏览器就给搜狗的服务器发送了一个 HTTP 请 求, 搜狗的服务器返回了一个 HTTP 响应.
这个响应结果被浏览器解析之后, 就展示成我们看到的页面内容,往往主体就是一个HTML内容.
- 一个网站=前端(网页)+后端(HTTP服务器):
网页 HTML,CSS,JS都是在浏览器上执行的.
都是在访问服务器的时候,从服务器下载到浏览器上,然后才能下载执行.
其它的应用程序,一般都是先下载安装,才能使用.网页是随时用随时下载.
- 使用网页的优势与劣势:
优势:服务器随时更新,用户就能用上新版本.
劣势:性能有限,很难提供一些复杂的,重复的操作.
2. HTTP 协议格式
HTTP 是一个文本格式的协议,可以使用抓包工具分析 HTTP 请求/响应的细节.
2.1 抓包工具(Fiddler)的使用
本质上是一个代理.
比如说,我想吃辣条,让我弟去跑腿.
这个时候,我和超市老板完成了交易,但是我们没有直接见面,而是通过我弟来进行的交互.而作为代理,我弟很清楚我和老板之间,交易的细节.
此时抓包工具就可以获取到浏览器和服务器之间的交互细节了.
也就可以拿到HTTP请求,和HTTP响应中的具体信息了.
抓包工具,是一种代理.
但是代理又不仅仅只是抓包工具,还有很多种体现形式.
代理客户端的,叫正向代理.
代理服务器的,叫反向代理.
左侧是当前机器上有哪些HTTP数据报在交互.
不仅仅能抓浏览器,而且能抓到所有程序的.电脑上的很多程序,都在后台和服务器悄悄地交互.
选中某个数据之后,右侧就能显示出详细信息.
右上角显示的是请求的详情.
右下角显示的是相应的内容.
这个就是抓取搜狗主页,交互过程.
这些标签页,就是站在不同的视角来解析请求和响应的.
最主要使用的方式是Raw.显示的HTTP原始的数据内容.
当前HTTP响应,经常会进行压缩(节省带宽)(响应可能比较大).点击就会解压缩.
3. HTTP请求
3.1 认识URL
URL:请求,就是客户端(浏览器)给服务器发起的一个数据.
这里要明确描述出,要访问的服务器是什么,要访问的服务器的资源是什么.
3.1.1 基本格式
出自于RFC标准文档.
举个例子:
虽然认识了query string(查询字符串)的格式,但不知道内容和含义.(这里的键和值的含义,都是程序员自定的).
实际上,URL来说,上述的几个部分,都是可以省略的,不是哪个部分必须得有.
3.1.2 URL中的可省略部分
- ①IP地址/域名省略,此时相当于是访问当前服务器的地址.
比如说:
访问B站主页,请求里须带有B站域名,响应内容就是B站主页的HTML.
这个HTML里又会触发一些其它的HTTP请求,这些后续触发的HTTP请求,就可以省略IP.
省略IP相当于使用和刚才获取B站HTML一样的IP.
- ②端口号省略
相当常见.
省略时,浏览器会自动加上端口.(这个端口表示的是访问目标服务器的哪个端口)
如果是HTTP协议,自动添加的端口就是80.
如果是HTTPS协议,自动添加的端口就是443.
- ③带层次的路径省略
比如:
https://www.sogou.com/
如果省略,相当于访问的就是/,/称为根目录.
服务器提供的资源,也是类似于目录结构一样的树形结构来组织的.
既然是树,就会有树根./就是根节点.
通过根节点就会对应到服务器的主页.(约定俗称的规则)
- ④查询字符串省略
有和没有,都是可以让后端代码根据情况来处理.
正是上述灵活性,是HTTP可以根据不同的需求场景,进行一些"自定制"工作,也就是HTTO协议成了非常广泛使用的协议.
3.1.3 URL encode
可以看出输入的C++,这里显示为C%2B%2B?
发现,当我们输入www.sogou.com/index.html的时候,页面就变了.
这个页面就会多了一些按钮,点击按钮,就能跳转.(html中的a标签,带有一个url)
- url里面就是带有query string的.
query string中可能会带有一些特殊符号.而这些特殊符号,可能在url本身就有一定的含义,就导致浏览器/服务器解析失败.
C++中+就属于特殊符号=>%2B.
:/?&=#同理,都需要转换.
url encode本质上就是转义字符!!!(不是\那种,另外一套规则)
- 转换规则:
把要转换的内容的二进制的每个人字节,都使用十六进制表示出来,然后每个字节前面加上一个%.
经过url encode之后,此时query string中就不会出现特殊含义的符号,浏览器和服务器才能正确识别.
3.2 认识方法(method)
HTTP请求的方法:
其中GET最常用,其次是POST.
方法描述的是"语义",即这次请求要干嘛.
GET:从服务器获取xxx
POST:向服务器传输一个xxx
实际上,GET,POST......不一定遵守之前的语义了.
3.2.1 GET方法
GET请求一般没有body.
3.2.2 POST方法
POST请求最常见的场景:登录和上传
①登录
空行,相当于是一个分隔符,分割了header和body.描述了body是从哪开始的.
body里的格式,其实是可以又很多种.
此时这个body格式,和刚才的query string非常类似.也是键值对,只不过是经过了urlencode的.
在登陆场景中,这里就会包含当前这次登录的用户名和密码等认证信息.
密码是加密的,一般密码是不会明文传输的.
②上传
此处的Value就是把整个图片都进行转码,转成字符串在这里填写.
3.2.3 POST和GET的区别
①最主要的区别,就在于:
- GET是把一些自定义的数据放到query string里,body通常是空的.
- POST是把一些自定义的数据放到body里,query string通常是空的.
都是要传输给服务器,放哪都是放,本质上没什么区别.
放在URL中,用户能直接看到.
放在body中,用户没法直接看到.
②上传和登录,还是使用POST更多:
- 登录的时候,涉及到用户名密码,属于比较敏感的信息,直接展示在URL里,会给用户造成一种"不安全"的错觉.
- 上传的时候,涉及到的内容比较长,比较多,直接放到URL里,显示不美观.
因为POST和GET数据放哪里本质上都可以,两者经常也可以相互替代!
[经典面试题]盖棺定论:GET和POST没有本质区别!!!
从习惯用法上来看,
- GET通常把数据放到query string中,用户能看到,浏览器收藏夹也能收藏.
- POST通常把数据放到body里,用户不能看到,收藏夹也不能收藏.
注意:网上有些资料,对于GET和POST的区别,解释并不正确.
- 1.比较长的数据放到body中(使用POST),原因是GET请求中的URL长度有限制.
×首先,RFC标准文档,明确说明了,对于URL的长度不做限制要求.
其次,当前的资源有限,当时的浏览器对于URL确实有限制,具体限制了多长,看不同的浏览器.(老黄历)
- 2.POST比GET更安全.
安全指的是,我们传输的数据,不容易被黑客截获,或者被截获了不容易被破解.
POST只是把传输的数据让普通用户没法直接看到,不影响黑客截获.
保证安全的关键,是对传输的敏感数据,进行加密!!!
- 3.GET和POST语义不同.
设计者最初是赋予了不同语义,但实践中不一定完全遵守.
比如有的公司,设计的所有接口都是POST.有的公司,同时提供GET和POST.
- 4.GET是幂等的,POST不是幂等的.(REC文档上,建议这么设计)
幂等:给相同的输入,每次都是相同的输出.
设计互联网产品,有些时候,也是要考虑幂等性的.
有的时候,期望是幂等的,有的时候,不幂等.
举个例子:像广告这种,就不能是幂等的,要根据用户,时间,地点,广告投放时间,广告主的出价情况......随时做出改变.
- 5.GET请求可以被缓存,POST请求不能被缓存.
有些操作,可能比较耗时,与其每次都重新计算,不如把结果保存下来.下次需要用的时候,直接获取.(缓存的前提是,幂等)
除了get和post还有哪些方法?(简单了解)
3.3 认识请求报头(header)
请求报头的整体的格式也是"键值对"结构.
每一行是一个键值对.
键和值直接使用 :空格来分割.
query string/body中的键值对,完全是程序员自定义的.
header中的键值对,主要是标准规定的.(有哪些键,对应的取值有哪些,都有规定),也有可以自定义的部分.
比较重要的:
Host | 表示服务器主机的地址和端口 |
Content-Length | 表示body中的数据长度 |
Content-Type | 表示请求的body中的数据格式 |
3.3.1 Host
Host里的内容,不是在url中已经有了吗,为什么还要再表示一遍?
通常情况下,Host里的内容和url是一致的,但是也有例外.比如使用了代理,就不一样了.
3.3.2 Content-Length
描述了body的长度是多少字节.
有的请求有body,有的没有.
如果没有这个body,这个字段就可以没有.
如果有body,这个字段必须有.否则就是非法请求.
body是从空行开始的.
从空行这里开始数,数Content-Length这么长,就是body结束了.
这是为了解决粘包问题.
- HTTP基于TCP.
当浏览器连续给服务器发起多个HTTP请求的时候,或者服务器连续多个返回HTTP响应的时候,服务器或者浏览器如何区分,从哪到哪是一个完整的HTTP数据呢?
1.使用分隔符
2.使用长度.
- HTTP两个都有:
如果是GET,没有body,使用空行,作为结束标记了.
如果是POST,有body,使用长度,区分结尾了.
3.3.3 Content-Type
针对这个数据,如何解析?如何理解?
HTTP协议有很多用途,传输的数据也有很多种类.
在HTTP请求中,Content-Type有三种主要的情况:
很多网站都会使用json,教务系统就是如此.
- 如果是响应,情况更复杂:
可能是
html:text/html
css:text/css
js:application/javascript
json:application/json
图片:image/png image/jpg
纯文本: text/plain
通过Content-Type就可以区分出body的数据的格式是什么.
尤其是浏览器,需要根据不同的格式来决定如何处理.
3.3.4 User-Agent(UA)
主要包含的就是当前机器的系统和浏览器的版本.
在浏览快速发展的时候,新的浏览器支持的功能更多,旧的支持的更少.
同一时刻,市面上有的人使用新的,有的人使用旧的.
- 举个例子,当你在开发一个网站时,是否要让这个网站带有视频音频js等功能呢?
因此,浏览器在发起HTTP请求的时候,要向服务器自报家门,告诉服务器我现在使用的是什么系统,什么浏览器上网,服务器就可根据这个信息,来分别对待.
实现兼容.让两边都满足需求.
老版本的返回简单网页,新版本的返回复杂网页.
UA现在主要用来区分,PC端(Windowsj/Mac)还是移动端(Android/IOS).
3.3.5 Referer
描述了,当前页面从哪里来.
如果你是通过浏览器地址来直接输入url/点击收藏夹打开的网页,这个请求中是不带Referer的,但如果是点击了某个网页的内容,产生了跳转,就是带Referer.
如上所述.此时Referer就是刚才的搜素结果页.
Referer是明文传输的.
是否会有人把Referer给偷偷改了呢?
在2014年左右的时候,这是一个相当普遍的现象!
是谁在修改???运营商(移动,联通,电信)
1.是否有能力?
有.访问百度/搜狗,流量都是通过运营商的设备(路由器/交换机)进行转发的.完全可以在路由器上搞个程序,分析请求的情况,如果发现是这种广告类的跳转请求,就修改Referer.
2.是否有动机?
有.运营商也有自己的广告平台.
把Rerfer改成了自己广告平台的Referer!
本来这次请求,是搜狗给广告主带来的,结果Referer被改了之后,在广告主看来,请求就是运营商的了,就会提高对运营商的营收.
当然运营商不是把全改,只改一小部分.
这个行为称为"运营商劫持",违法.
使用HTTPS,进行加密传输,这个时候情况就不一样了.
3.3.6 Cookie
是浏览器本地存储数据的一种机制.
键值对之间,使用;分割.键和值之间,使用=分割.
与此同时,用户拿着网页,操作的过程中,也会产生很多"临时性"的数据.
像临时数据,有的可以放到服务器这边存储(下次就能直接获取到了)
有的不太重要的,就直接放到浏览器这边存储(下次访问也可以直接用,但是换个电脑可能就没了)
其中,Cookie就是一个主要的保存机制.
比如,我在B站观看视频的时候,勾选"循环",就可以在Cookie中写入一个数据"循环"=true
浏览器就会自动存储这个数据(硬盘),后续再次访问B站,浏览器就能自动把这个数据读出来,并且放到HTTP请求中.
B站就知道当前用户是否希望开启循环了.
- 那浏览器要保存数据,为什么要放到Cookie中,直接放到硬盘,写入一个文件不行吗?
当然不行.
如果让网页能够轻易访问你的文件系统,非常危险!!!
如果网站给你电脑上写个病毒,或者直接把你硬盘上已有的数据给删掉......
为了保证安全,浏览器会对网页的功能做出限制(禁止直接访问硬盘,就是其中一个规则)
为了保证安全,同时又能存储数据,浏览器就提供了Cookie功能.
是按照键值对的方式来存储一些字符串,这些键值对往往都是服务器返回回来的,浏览器把这些键值对按照"域名"维度(不同的网站,Cookie是独立的,这些内容,都是程序员自应用的,类似于query string),分类存储.
一个网站,Cookie中会存储很多键值对.
往往会有一个很重要的键值对,是用来表示用户的"身份信息"的.
标识当前请求是来自于哪个用户的.
尤其是有的时候,登录了一个网站之后,后续再次访问这个网站的时候,都不用重新登录!!!
并且关了电脑,第二天再次访问,仍然不必重新登录.(服务器能识别登陆状态)
为了实现身份识别的效果,不仅仅需要Cookie来支持,在服务器这边,也需要一个Session机制来支持.
怎么完成配合呢?
举个例子:
在医院的看病流程是什么样?
如果是第一次来到这个医院,首次挂号的时候,会办一张就诊卡.同时在医院的系统里,会给你创建一个电子档案.
就诊卡里,存储了患者的身份标识.是唯一的.
可以把这些电子档案,想象成使用hash表来组织.key就是身份标识,value就是电子档案的详情.
当排到我之后,第一件事是刷一下就诊卡.此时各种信息,就显示在医生的电脑上了.
刷卡的时候,读卡器就读到了芯片中我的身份标识,就可以通过这个身份标识找到了对应的电子档案,也就知道我的详细情况了.
首次访问网站,注册不考虑,登录成功之后,就相当于,网站给你一个就诊卡(身份标识)
身份标识就通过服务器返回给浏览器的响应,保存在浏览器的Cookie中了(键值对)
与此同时,网站服务器那边,也会创建出一个对应的Session(电子档案),Session中就会记录我的一些关键信息.
网站服务器肯定不止一个用户,有很多用户,每个用户都有自己的
Session,并且他们的SessionId各不相同,服务器就会使用类似于hash表这样的方式,以SessionId为key,以Session为value,把所有的数据组织起来.
后续访问网站的其它页面(相当于去各个科室检查),都会在请求的Cookie字段中,带上刚才这里的SessionId(就是先刷卡),服务器就可以根据SessionId就知道了你当前用户的身份信息了.
- 简单总结:
4. HTTP响应
4.1 状态码
状态码,就是对这次响应的定性.(成功,失败等情况)
200表示成功(计算机中,通常会使用"数字表示结果,使用不用的数字表示不同的失败原因")
- 常见的状态码:
成功: 200OK
重定向: temporarily 重定向,浏览器跳转到其它的页面上
请求错误: 403 Forbidden 没有权限 404 Not Found 你要访问的资源不存在
服务器错误: 502 Bad Gateway 服务器挂了 Timeout 服务器响应超时了(多半是服务器出问题了)
- [面试题]你都知道哪些HTTP状态码,都是什么意思?
重定向:
举个例子:"呼叫转移"
比如说我有一个手机号码:155,某一天我换了个手机号码:166.
就可以去运行商,办理呼叫转移业务.如果有人拨打155,就自动转接到166上.
HTTP的重定向,就是这么搞的!!!
5. 构造HTTP请求的四种方法
实际开发中,经常需要能够手动的构造出HTTP协议的请求:
1.通过html的form表单
2.通过js的ajax
3.java代码
4.借助一些第三方工具
5.1 通过 form 表单构造 HTTP 请求
HTML也是一种编程语义,和Java风格差异很大.
描述一个"形态",一个网页上,都有什么.
Java是在描述一个逻辑,先干什么,后干什么,是"动作".
- html非常有特点:
1.由标签构成,标签可以成对出现,也可以单独出现.
2.标签可以嵌套.
下面通过html中的form标签(表单)构造HTTP请求:
抓包:
form表单,只能支持get和post!!!
5.2 通过 ajax 构造 HTTP 请求
asynchronize 异步
同步的等待,等待的职责是放到了发起者的身上.
异步的等待,等待的职责是放到了被发起者的身上.
ajax是一种异步的通信方式.
通过代码,发起了http请求,请求发出去之后,js代码就继续向下执行了.
当服务器的响应回来了之后,就会自动的通知到代码中,进一步就能处理响应了.
js中,{ }表示的是js的对象.(键值对)
{ }里可以有多个键值对.
键值对之间,用,分割.键和值之间,使用 :分割.
键固定都是string类型,可以写'也可以写"也可以不写.
值可以是数字,字符串,数组,对象.
这里的type,不仅支持get和post,也支持其它各种方式.
抓包:
5.3 通过 Java socket 构造 HTTP 请求
java等一系列代码:
使用Java构造,本质上就是一个TCP的客户端.
创建一个Socket对象,往里面按照HTTP协议的格式写数据即可.
5.4 通过postman构造 HTTP 请求
使用第三方工具,构造HTTP请求.
Postman
并且这里同时可以生成代码:
6. HTTPS
HTTPS也是基于HTTP的,HTTPS就是在HTTP的基础上,进行了加密.
6.1 加密是什么
明文:真正要传输的数据.
密文:经过加密之后的数据.
密钥:在加密和解密过程中起到关键作用.
对称加密:加密和解密,使用的是相同的密钥.
非对称加密:加密和解密,使用的是不同的密钥.
分别称为"公钥"和"私钥",使用公钥加密,私钥就能解密.反之亦然.
6.2 HTTPS的工作过程
最简单的保证安全的做法:
引入对称密钥,针对传输的数据(HTTP的header和body)进行加密
6.2.1 引入对称加密
每个客户端,都需要有一把自己的对称密钥(不同客户端的密钥也要不同)
如果客户端生产了密钥,就需要把密钥传输给服务器.
那么问题来了:
此时,黑客已经知道了密钥,后续使用这个密钥加密传输,传输的数据能被黑客解密.
那么就需要想办法,把密钥安全的传输到对端.
需要对这个密钥进行加密.
那如果使用对称密钥对刚才的对称密钥进行加密,还是不行.
此时,如果继续使用对称加密,不管几层,都不安全.
那么就使用非对称加密,针对对称密钥进行加密了.
6.2.2 引入非对称加密
此处使用非对称加密,只是用来针对对称密钥进行加密,而不是加密http的数据.
后续数据的加密还是使用对称加密的.
非对称加密,运算量很大,效率比较低.
对称加密,运算量小,效率更高.
对上述的过程,还存在一个严重的问题,中间人攻击:
黑客可以使用中间人攻击的方式,仍然能够拿到对称密钥.
解决中间人攻击的关键,需要让客户端能够确认当前收到的公钥,确实是服务器返回的,而不是黑客伪造的!!!
引入了证书机制.
6.2.3 引入证书
需要有一个第三方的认证机构,通过第三方机构作保,来确认当前的公钥是有效的.
服务器会向第三方公证机构申请证书,这个证书里,就会包含很多的属性:
网站的域名,证书过期时间,公钥,数字签名......
这个数字签名,是针对其它数据属性进行的一个验证的机制.
公证机构,在生成证书的时候,会先针对证书中的其他属性,生成校验和.
公证机构,还会使用自己的私钥(不是服务器的私钥)针对上述校验和进行加密,这样其他人就无法重新生成这个校验和.
客户端拿到证书之后,就会对证书进行验证.(检查一下证书是否合法,是否被篡改)
客户端持有认证机构的公钥,就可以针对数字签名进行解密,得到了校验和的明文.
接下来客户端就可以按照同样的算法,把证书中的其它属性再算一次校验和,和证书中的校验和进行对比,判断证书.
- 问题1:
如果黑客把证书的数据篡改了(比如把公钥替换成了自己的)?
此时校验和不同,客户端会发现.
- 问题2:
黑客能否对数字签名进行替换?
不能!!!
数字签名,是先计算校验和,在使用认证机构的私钥进行加密,黑客不知道认证机构的私钥是什么,所有无法重新对校验和进行生成数字签名的过程.
- 问题3:
黑客是否自己也去第三方机构,申请一个证书,把整个证书替换成自己的?
黑客可以这么做,但是没用.
证书中有网站的域名,黑客证书的域名肯定不能和网站的域名一样,审核无法通过.
当然,黑客可以把自己伪装成认证机构,骗客户端按照自己的公钥,此时就可以光明正大的替换证书中的数字签名.