网络模型
基础:
MAC地址:确认硬件的物理位置 一个网卡一个mac地址 一个设备多个网卡会有不同的mac地址
IP地址:网络地址 一个主机对应一个ip地址 ip地址构成是网络号+主机号 /网络号+子网号+主机号
OSI七层模型
- 物理层 传输原始比特流
- 数据链路层 物理寻址 确定网卡位置(MAC地址)
- 网络层 网络寻址 IP地址 建立主机到主机之间的通信
- 传输层 有了MAC+IP后 确定端口号 TCP传输控制协议 建立端口到端口的通信(每台机器上不同进程之间)
- 会话层 建立和断开连接
- 表示层 数据格式转换
- 应用层 (各种应用程序协议 HTTP、FTP、SMTP、POP3)最终负责建立连接,为应用程序提供网络服务;提供计算机网络与最终呈现给用户的界面
TCP/IP四层模型
- 数据链路层(物理+数据链路层) 物理上把主机连接起来
- 网络层 ip层 建立主机和主机之间通信
- 传输层 建立端口到端口的通信 TCP UDP
- 应用层(会话层+表示层+应用层)提供了一些常用的协议规范,比如FTP、SMPT、HTTP、DNS等。
在浏览器输入url后会发生什么
整体流程:
- 从浏览器输入网址后,首先要经过域名解析,因为浏览器并不能直接通过域名找到服务器,而是通过IP地址找到对应的服务器,DNS将域名解析为IP地址;
- 浏览器通过IP地址找到服务器,三次握手进行TCP连接端口到端口;
- 浏览器发送HTTP请求报文;
- 服务器处理请求,并返回HTTP响应报文;
- 浏览器拿到响应文本HTML后,开启渲染进程,解析渲染页面;
- 当数据传送完毕后,断开TCP连接。
TCP协议
TCP 传输层的协议 保证数据传输的有序和完整
三次握手
SYN synchronize 同步
ACK acknowledgement 确认
- 初始时客户端服务端都是CLOSED状态。客户端主动打开,服务器被动打开,进入LISTEN状态。
- 第一次握手: 客户端随机初始化序列号X,设置SYN同步标志位为1,用来建立连接,然后发送SYN报文给服务端,客户端进入SYN_SEND等待服务端确认的状态。
- 第二次握手: 服务器端收到客户端发来的SYN报文后。服务器自己也生成初始序列号y,SYN同步标志位和ACK确认标志位置1,ack确认号=x+1的SYN报文作为客户端建立连接请求的应答。服务器处于SYN_RECEIVED状态。
- 第三次握手:客户端收到服务端的确认应答后,检查ack确认号是否x+1,ACK确认标志位是否=1。若正确就返回ack确认号为y+1,及ACK=1的数据包(ACK报文)发送给服务器,确认服务器的应答。客户端进入ESTABLISHED状态。
- 服务器端收到应答包,检查ack确认号是否=y+1来确认是否建立连接成功,服务器进入ESTABLISHED状态。
为什么是三次握手不是两次握手?
为了确认服务器和客户端的发送和接收能力都没有问题。
第一次握手,服务器确认了客户端的发送能力ok,服务器接受能力ok
第二次握手,客户端确认服务器的发送能力ok,客户端的发送能力和接受能力ok,但服务器此时不知道客户端那边接受能力是否ok,是否收到了这边的确认请求。
第三次握手,服务器确认了客户端的接受能力ok。
第三次握手主要是为了确认客户端那边是否接受到了第二次握手的数据,如果不进行第三次握手,可能会造成服务器这边确认连接开着端口,但客户端那边没连接上不发数据的尴尬情境。
前两次握手不能传数据 第三次握手可以携带数据了
四次挥手
TCP连接是全双工的(数据可以在两个方向上同时发送)
ps 半双工是同一时间只能向一个方向发数据
1。第一次挥手:客户端发送一个 FIN 报文,假设此时的seq=u。表示客户端请求关闭连接了。此时客户端处于FIN_WAIT1状态。
2、第二次握手:服务端收到 FIN 报文之后,发送ACK确认标志位=1,ack确认号为u+1的响应报文,表明已经收到客户端的报文了,但是可能服务器还有数据传输,所以服务端处于 CLOSE_WAIT状态。
3、第三次挥手:当服务器数据发送完了,发送FIN为1、ack=u+1、seq=w的FIN报文,准备关闭连接。此时服务端处于 LAST_ACK 的状态。
4、第四次挥手:客户端收到FIN报文后,向服务器进行应答,发送ACK为1、ack=w+1、seq=u+1的ACK报文。此时客户端处于 TIME_WAIT 状态。
5、服务器会等待客户端的应答后才会真正断开连接,如果服务器没有收到应答报文则会重传。
6、客户端等待2*报文段最大生存时间MSL Maximum Segment Lifetime 后依然没有收到回复,说明服务器端已正常关闭,客户端也可以关闭连接了。
为什么连接的时候是三次握手,关闭的时候却是四次挥手?
而三次握手的时候 收到连接请求时 服务端是发SYN+ACK报文代表同步和确认 而服务端收到关闭请求的时候 可能还有数据没发送完 所以要发一次ACK和一次FIN报文 不能一起发送 所以多了一次挥手。
为什么要等待2个报文段最大生存时间
假设第四次挥手的ACK应答包丢失,服务器在1MSL没有收到应答报文,则会重传FIN报文,在2个报文段最大生存时间之内,如果客户端再次收到FIN报文,就重发ACK应答报文并重启计时,保证双方都可以正常进入关闭状态。
否则新连接建立时,端口重用,可能会有上一次连接中残留的数据。
如何保证传输的可靠性
1、确认和序列号
TCP协议面向字节流,为每个字节都编上序号。在发送时多个字节组成报文段发送。
序号seq字段 指的是一个报文段第一个子节的序号
确认号ack字段 指的是希望收到的下一个报文段的第一个字节的序号
采用累计确认 对同时收到的多个报文进行确认
2、超时重传 有最大报文生存时间MSL,超过时间没收到确认报文就重发。
...待补充
TCP VS UDP
- TCP是面向有连接型,UDP是面向无连接型即发送数据前不需要建立连接;
- TCP是可靠的,UDP只管传送不管丢包;
- TCP是一对一传输,UDP支持一对一、一对多、多对一和多对多的交互通信;
- TCP是面向字节流的,即把应用层传来的报文看成字节流,将字节流拆分成大小不等的数据块,并添加TCP首部;UDP是面向报文的,对应用层传下来的报文不拆分也不合并,仅添加UDP首部;
- TCP数据传输慢,但占用资源多,UDP数据传输快,但占用资源少
- TCP适用于对要求稳定的如文件下载、浏览器访问网页、发邮件; UDP适用于即时通信,比如直播、语音电话
http协议
http是应用层的协议,客户端和服务器之间的通信协议
http缓存
分为强制缓存和协商缓存
请求方法
GET:对服务器资源的简单请求
POST:用于发送包含用户提交数据的请求
PUT:传数据给后端,新增或修改资源,侧重于创建数据即INSERT语句
DELETE:请求删除数据 对应DELETE语句
HEAD: 类似GET方法,但只返回响应报文的响应行,没有响应体。常用来确定资源的有效性及更新日期时间等。
OPTIONS:
GET, POST, PUT, DELETE OPITONS
get vs post
get是直接获取信息 post允许向服务器那边传送数据
get的请求参数放在url后面(?=的形式) 请求参数有大小限制
post的请求参数放在请求体的数据里 不会在url里显示 请求参数没有大小的限制
URL
URL:统一资源定位符,是一种资源位置的抽象唯一识别方法。
组成:<协议>://<主机>:<端口>/<路径>
端口和路径可以省略(HTTP默认端口号是80)
请求报文
响应报文
状态行 响应头 响应体
状态行 协议+版本 状态码 状态描述
响应头 set-cookie content server
响应体 响应数据eg html。。。
响应状态码
www.runoob.com/http/http-s…
直接看这个↑
无状态协议
get post的区别
从本质上看: GET用于信息获取,即查询操作; POST是用于传输信息,可以用于增删改。
非本质区别: 1、缓存不同:GET请求一般都会缓存,POST不会缓存;
2、参数长度限制不同:GET请求的参数会附在URL后面,POST的数据放在请求体里,因此GET有长度限制,POST没有。也正因如此,POST安全性比GET安全性高。
3、回退和刷新不同:GET直接回退或刷新不会有影响,POST回退或刷新会重新提交数据
4、历史记录不同:GET的参数会被保存在浏览器历史中,POST不会。
HTTP 1.0 2.0 3.0
HTTP 1.0 持久连接
HTTP vs HTTPS
解决跨域问题:
跨域和同源
浏览器的同源策略:请求的url和当前页面必须同源,指协议,域名,端口都要相同,其中有一个不同都会产生跨域。
1.代理服务器
配置代理服务器,请求用代理服务器进行转发,服务器之间没有同源限制。
devServer: {
proxy: {
'/api': { // 只对请求路由以/api开头的请求进行代理转发
target: 'http://gmall-h5-api.atguigu.cn', // 转发的目标url
changeOrigin: true // 支持跨域
}
}
},
2.JSONP
有src属性的如img iframe script标签 不受同源策略的限制
JSONP 是非正式的传输协议 利用script标签的跨域能力实现跨域请求 只能用于get请求
客户端这边动态创建一个script标签,并指定拿到数据后的回调,通过script标签的src属性向服务器接口发请求
在服务器 把要传的数据以JSON的格式包装在客户端创建的回调函数里 写在一个js文件里 把该js文件返回给客户端
客户端请求到脚本文件后 会立即执行 这样我们之前定义的回调函数就可以直接调用 从而实现跨域
3.CORS
CORS(跨域资源共享)官方的跨域解决方案,由服务端进行配置,支持get和post请求。
简单请求
满足以下条件: 1、请求方法是get/post/head之一
2、http请求头在Accept、content-type等几个字段中
简单请求流程:
1、浏览器发送简单请求时,在请求头的origin字段中写明该请求的来源,包括协议、ip地址和端口号
2、服务端收到请求,如果同意,则在响应报文的响应头中添加access-control-allow-origin字段,和origin一样
非简单请求
1、浏览器在正式请求之前,会发送一次options请求作为预请求,包括请求头内容有origin,Access-Control-Request-Method请求方法和Access-Control-Request-Headers自定义请求头。
Origin:与简单的请求相同。
Access-Control-Request-Method: 请求自身使用的方法。
Access-Control-Request-Headers: (可选)自定义的头部信息,多个头部以逗号分隔
2、服务器收到请求之后,如果同意,会发送响应报文,包括
Access-Control-Allow-Origin:与简单的请求相同。
Access-Control-Allow-Methods: 允许的方法,多个方法以逗号分隔。
Access-Control-Allow-Headers: 允许的头部,多个方法以逗号分隔。
Access-Control-Max-Age: 将这个 Preflifght 请求缓存多长时间(以秒表示)。
3、当预请求通过之后,之后的请求就和简单请求一样了。
前端安全
XSS(Cross-Site Scripting)跨站脚本攻击
1、反射型XSS(非持久型)
常出现在搜索功能中,攻击者将脚本混在URL里,服务端接收到URL将恶意代码当做参数取出并拼接在HTML里返回,浏览器解析此HTML后即执行恶意代码
2、存储型XSS(持久型)
常出现在表单等提交功能中,比如发表评论,攻击者将脚本提交到服务端的数据库里,用户访问数据库内容时,浏览器执行脚本被攻击。
3、DOM型XSS(基于本地)
一般是提供一个免费的wifi,但是提供免费wifi的网关会往你访问的任何页面插入一段脚本或者是直接返回一个钓鱼页面,从而植入恶意脚本。这种直接存在于页面,无须经过服务器返回就是基于本地的XSS攻击。
防御:
1、避免把不可信的数据直接作为html拼接到页面,.innerHTML、document.write()时要特别小心,应尽量使用innerText,.setAttribute() 等方法
2、如果必须拼接html时,对 HTML 做充分转义,(如对于引号、尖括号、斜杠进行转义)
(vue react等主流框架已经做好了转义 如vue不能在template标签中插入script标签),有防止xss的插件js-xss
3、对于显示富文本,不能全部转义,可以建立白名单内容安全策略(Content Security Policy CSP),告诉浏览器哪些资源可以执行
设置 HTTP Header 中的 Content-Security-Policy
Content-Security-Policy: script-src 'self';
object-src 'none';
style-src cdn.example.org third-party.org;
child-src https:
设置 meta 标签的方式
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">
4、其他措施
HttpOnly Cookie 给cookie中设置HttpOnly属性,那么通过js脚本将无法读取到cookie信息,这样能有效的防止XSS攻击,窃取cookie内容
CSRF(Cross-site request forgery) 跨站请求伪造
利用用户的登录凭证,冒充用户,发送恶意请求。
步骤 1、登录受信任网站 A ,并在本地生成保存Cookie;
2、在不登出 A 情况下,访问恶意网站 B,
3、B网站利用本地的cookie作为身份认证,伪造用户向A网站发送请求。
例如:登录购物网站 A 之后点击一个恶意链接 B,B 请求了网站 A 的下单接口,结果是在网站 A 的帐号生成一个订单。
原理是:当用户登陆了网站A以后,cookie会保存到本地,每次对网站A发起请求时,浏览器会默认带上这个cookie,服务端以cookie来校验请求发起人的身份。B网站对A网站发起请求(通过script img等标签的src发get请求 或用表单发post请求,浏览器对img等标签和post表单没有跨域限制),也会带上用户登陆信息cookie,所以最后成功发起了CSRF。
防御 1、使用Cookie的SameSite属性
在 HTTP 响应头中,设置 Cookie 时,带上 SameSite 选项,限制第三方的cookie。
2、添加Token验证
添加到http请求头或参数中,并在服务器建立一个拦截器来验证这个token。
3、添加验证码(如滑动图片)
确保请求是用户真人行为而不是黑客行为
4、验证 HTTP请求头中的 Referer 字段。
其记录了当前请求的来源地址,但是对于某些浏览器,比如 IE6 或 FF2,可以篡改 Referer 值
zhuanlan.zhihu.com/p/259879164
浏览器存储
cookie sessionStorage localStorage
| 区别 | cookie | localStorage | sessionStorage |
|---|---|---|---|
| 生命周期 | 可设置失效时间,没有设置的话,默认是关闭浏览器后失效 | 除非被手动清除,否则永久保存 | 仅在当前网页会话有效,关闭页面或浏览器后就会被清除 |
| 存放数据大小 | 不超过4kb | 5MB左右 | 5MB左右 |
| 使用范围 | 同域名下都会共享,(子域可以)当前域下的js脚本不能访问其他域下的 cookie 因为同源策略 引出同源策略和跨域 | 相同浏览器的同源窗口都会共享 | 通过跳转的同源页面可以共享sessionStorage,同一个页面的不同窗口不可以共享 |
| http请求 | 会自动把当前域名下所有未过期的Cookie一同发送给服务器 | 仅在浏览器中保存,不参与和服务器的通信 | 仅在浏览器中保存,不参与和服务器的通信 |
| 应用场景 | 本职工作并非本地存储,而是维持状态 | 本地存储工作 | 本地存储工作 |