通信协议
客户端浏览器与服务器之间要实现网页内容的传输,则需要通信双方遵循网页内容传输协议,又叫超文本协议(http
协议)
HTTP
协议(应用层)
用于客户端与服务器之间的通信,无状态协议
HTTP
通信的缺点
- 使用明文通信,可能被窃听
- 不验证通信方的身份,可能遭遇伪装的客户端发送请求,或者伪装的服务器响应数据
- 无法验证报文的完整性,可能在传输途中被拦截篡改
HTTPS
通信的优点
https
协议实际上就是身披SSL
协议的http
协议- 实现通信加密,认证通信方身份,报文完整性保护
HTTPS
通信的缺点
- 通信慢,因为在
http
协议与tcp
建立连接之前还必须进行SSL
通信。SSL
协议在客户端和服务器端都需要进行加密和解密操作,消耗硬件资源,处理速度变慢
HTTPS协议的加密
近代加密算法中加密算法是公开的,密钥是保密的
- 共享密钥:加密和解密用的同一个密钥,也叫对称算法
- 公开密钥:加密用的公钥是公开的,解密的私钥是非公开的,也叫非对称密钥
https
加密采用的是共享密钥和公开密钥并用混合的加密机制,在交换密钥的环节使用公开密钥加密方式,在之后的交互请求阶段使用共享加密的加密方式
ARP
协议
一种解析地址的协议,可以根据通信方的IP
地址反查出对应的MAC
地址。数据包发送过程中中转时使用
TCP
协议(传输层协议)
提供可靠的字节流服务。将大数据块分割成以报文为单位的数据包发送给对方,并能够确认数据是否发送到对方。
TCP
三次握手确保数据送达到对方:
- 发送端发送一个带有
SYN
标识的数据包, - 接收端收到后返回一个带有
SYN/ACK
的数据包, - 接收方最后再发送一个带有
ACK
标识的数据包来结束握手。
URL
统一资源定位符
绝对地址,相对地址
URI
统一资源标识符
由某个协议方案表示的资源的定位标识符,协议方案是指访问资源所使用的协议类型
IP
协议(网络层)
将数据包发送给对方
DNS
协议(应用层)
提供域名到IP
地址之间的解析服务
CDN
即内容分发网络,CDN
就是根据用户位置分配最近的资源,提高访问速度
Web安全
客户端验证:所有客户端验证都是不可靠的,保留客户端验证是为更早的识别错误
服务器端验证:输入值验证,输出值转义
XSS
攻击
跨站脚本攻击,指通过在存在安全漏洞的Web
网站的用户的浏览器运行非法的HTML
和JavaScript
进行攻击
危害:骗取用户个人信息,利用脚本窃取用户Cookie
值,在用户不知情的情况下发送恶意请求
防护:在用户输入点做字符串校验,输入值不能包含<, <
CSRF
攻击
跨站请求伪造,攻击者盗用用户身份发送请求
危害:盗用用户身份信息
防护:对接口做Token
校验,在接口请求头中添加Token
SQL
注入
指针对Web应用使用的数据库,通过运行非法的SQL
来进行攻击
危害:非法篡改数据库
防护:
CSV
注入
公式注入,将一些非法字符注入到Excel
文件中
危害:篡改Excel
表中的数据
防护:对导入的文件做特殊字符校验,不能以@+-=
开头
DoS
攻击
通过海量请求导致服务器资源耗尽,或者通过攻击安全漏洞使服务器停止响应。
DDoS
攻击
多台机器发起的DoS
攻击称为DDoS
攻击,DDoS
攻击通常利用感染病毒的计算机作为攻击者的攻击跳板
HTTP请求消息的组成部分
http
请求消息由请求行,请求头,空行,请求体四个部分组成
请求行: 由请求方式, URL
, HTTP
协议版本三部分组成
请求头: 常见字段, 用于接口校验的token
常放入请求头中传给服务器校验
空行: 又来分割请求头和请求体
请求体: 存放需要提交到服务器的参数, post请求才有请求体, get请求没有请求体
HTTP响应消息的组成部分
http
响应消息由响应行, 响应头, 空行, 响应体四部分组成.
HTTP响应状态码
原生JS中的AJAX
ajax
是一种无需加载整个网页的情况下, 更新部分网页的技术
https://www.runoob.com/ajax/ajax-xmlhttprequest-create.html
// 创建XHR对象 xhr.readyState = 0
let xhr = new XMLHttpRequest()
// 建立链接 xhr.readyState = 1
// async 为true则为异步,为false则为同步
xhr.open('get', URL, async)
// 如果需要设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 发送请求 xhr.readyState = 1
xhr.send()
// 监听readystatechange()事件
xhr.onreadystatechange = function() {
// readyState = 2,3,4
if(this.readyState === 4 && this.state === 200) {
console.log('请求成功')
}
}
ajax
的其他特性
// 设置超时时间
xhr.timeout = 30
// 设置超时以后的处理函数
xhr.ontimeout = function () {
console.log('请求超时了!')
}
// 文件上传事件,可监听文件上传进度
xhr.upload.onprogress = function(e){
// e.loaded 已经上传的大小
// e.total 文件总大小
// 上传进度
Math.ceil((e.loaded/e.total)*100)+"%";
}
// 文件上传完毕事件
xhr.upload.onload = function() {
// 此时readyState=4,请求已完成,数据传输完成
}
文件上传下载
// 文件下载
<a href="文件地址" download="文件名"></a> // 利用a标签的href下载文件
window.location.href = '文件地址' // 利用location的href属性下载文件
//文件上传, multiple:可选多个文件,accept:限制可选文件类型
<input id="myFile" type="file" multiple accept=".xlsx,.xls,xlsm" @change="changeFile"></input>
// 监听文件的改变
changeFile() {
let myFile = document.querySelector('#myFile')
let formData = new FormData()
formData.append('file',myFile.files[0])
}
Jquery中的AJAX
https://www.runoob.com/manual/jquery/
// GET请求, $.get(URL, params, callback)
// POST请求, $.post(URL, params, callback)
// $.ajax更常用
$.ajax({
type: '',
url: '',
data: {},
headers: {},
success: function(res) {
console.log('成功时的回调函数')
},
error: function(err) {
console.log('失败时的回调函数')
},
complete: function(res) {
console.log('无论成功与否都会调用')
}
})
其他API
// 设置ajax全局默认选项
$.ajaxSetup({
// 可以设置ajax所有选项
// 设置请求头
headers: {
wannaToken: localStorage.getItem('wannaToken') || ''
},
// 设置回调函数
complete: (res) => {
if(res.responesText === 'TOKEN_ERROR') {
localStorage.removeItem('wannaToken')
location.href = '去登陆页面'
}
}
})
// jquery的请求拦截,请求发送前都会走
// options: 当前ajax请求的所有参数选项
// originalOptions: 提供给ajax方法未经修改的选项
// jqXHR: 当前请求的jqXHR对象
$.ajaxPrefilter((options, originalOptions, jqXHR) => {
options.url = 'http://地址' + options.url;
// 配置ajax请求头 当请求地址为/my的时候添加请求头
if (options.url.indexOf('/my/') != -1) {
options.headers = {
Authorization: localStorage.getItem('token') || ''
}
}
// 无论请求成功还是失败,最终都会调用complete回调
options.complete = function(res) {
if (res.responesText === 'TOKEN_ERROR') {
localStorage.removeItem('token');
location.href = '去登陆页面';
}
}
})
// loading效果
// $(document) 会监听当前文档内所有的ajax请求
//Ajax 请求开始时,执行 ajaxStart 函数
$(document).ajaxStart(function() {
$('#loading').show()
})
//Ajax 请求结束时,执行 ajaxStop 函数
$(document).ajaxStop(function() {
$('#loading').hide()
})
Axios请求
文档地址:https://www.axios-http.cn/docs/intro
更现代的请求方式, 基于promise
可用于浏览器和node.js
的客户端, 自动转换JSON
数据格式, 可设置请求拦截和响应拦截等配置项
安装
npm install axios
导入
import axios from 'axios'
基础用法
// post 请求
axios({
method: 'post',
url: '',
data: {},
headers: {}
})
// get 请求
axios({
method: 'get',
url: '',
params: {},
headers: {}
})
get
请求:axios.get(url[, config])
// GET请求, DELETE请求
// 传统?拼接参数请求
axios.get('url?id=1')
.then((res) => {
console.log('请求成功时的回调')
}).catch((err) => {
console.log('请求失败时的回调')
}).finally(() => {
// 总是会执行
})
// 对象形式传参
axios.get('url', {params: {}}).then(() => {}).catch(() => {}).finally(() => {})
post
请求:axios.post(url[, data[, config]])
// POST请求, PUT请求
axios.post('url', {}).then(() => {}).catch(() => {}).finally(() => {})
全局配置
// 配置公共的请求头
axios.defaults.baseURL = 'https://api.example.com';
// 配置 超时时间
axios.defaults.timeout = 2500;
// 全局设置 axios 发送请求带上cookie,
// 在跨域请求时,当配置了xhr.withCredentials = true时,必须在后端增加 response 头信息Access-Control-Allow-Origin,且必须指定域名,而不能指定为*。
// 如果在同域下配置xhr.withCredentials,无论配置true还是false,效果都会相同,且会一直提供凭据信息
axios.defaults.withCredentials = true
// 配置公共的请求头
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
// 配置公共的 post 的 Content-Type
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
创建实例
// 创建axios实例,并传入需要的配置项
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'},
responseType: 'json', // 浏览器响应类型,默认为json
withCredentials: false // 表示跨域请求时是否需要使用凭证
});
拦截器
// 请求拦截, 在每一次请求前做一些操作,根据http状态码判断走成功还是失败回调,200~300走成功,400~500走失败
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
// 在这里配置请求所需的配置
if (Cookies.get('token')) {
config.headers['token'] =Cookies.get('token')
}
return config;
}, function (error) {
// 对请求错误做些什么
Message.error(error.message || '请求失败')
return Promise.reject(error);
});
// 响应拦截
service.interceptors.response.use(
// response.status === 200 时,走成功回调
(response) => {
// 在这里处理接口返回的结果
// console.log(response, '==response==')
if (response.data.code === '200' || response.data.code === '0') {
// 请求成功 抛出接口返回数据
return response.data
} else if (response.data.code === '401' || response.data.code === '410') {
// 用户信息已过期 或者用户已离职
// 清除登录信息
Cookies.remove('token')
// 跳转至登录页
setTimeout(() => {
location.href = `${location.origin}/login?backUrl=${location.href}`
}, 500)
} else {
// 抛出错误
Message.error(response.data.message || response.data.msg || '请求错误')
return Promise.reject(response.data.message || response.data.msg || '请求错误')
}
}, (error) => {
// response.status !== 200 时,走失败回调
// 对响应错误做点什么
Message.error(error.message || '请求失败')
return Promise.reject(error)
}
)
其他请求知识
Restful API
Restful API
:新式API
,同一个请求路径可以进行多种操作
GET
:查询
DELETE
:删除
POST
:添加
PUT
:更新
Restless API
:传统API
,同一个请求路径只能进行一个操作,一般只有POST\GET
传参格式
POST
请求传参的四种编码方式, 也就是Content-Type
的四种不同的值
// application/x-www-form-urlencoded 默认,在发送前对所有字符进行编码
// multipart/form-data 不对字符编码。当使用有文件上传控件的表单时,该值是必需的。
// application/json 最常用, JSON数据类型
// text/xml (xml) 文本格式
编码与解码
encodeURI
与decodeURI
encodeURI()
是javascript
中真正用来对URL
编码的函数. 它着眼于对整个URL
进行编码,因此除了一些常见的符号以外,对其他一些在网址中有特殊含义的符号也不进行编码.例如"/ : ' @ # & ? = + $ ,"
encodeURIComponent
和decodeURIComponent
它用于对URL
的组成部分进行个别编码,而不用对整个URL
进行编码. 对在encodeURI()
中不被编码的符号都会进行编码
跨域
同源:协议、域名、端口都相同,则两个页面为同源页面
同源策略:是浏览器的一个安全功能,限制非同源网站之间的交互行为。
跨域带来的问题
- 限制
DOM
访问,无法获取跨域页面的dom
- 限制
cookie
访问,无法获取跨域页面的cookie
- 限制
ajax
请求(实际请求已发送,服务器也会响应,只是响应结果被浏览器拦截了)
解决办法:
CORS
策略:Cross-Origin Resource Sharing(跨域资源共享),由一系列http
响应头组成,是用于控制浏览器校验跨域请求的一套规范,服务器依照 CORS 规范,添加特定响应头来控制浏览器校验
// 处理预检请求
app.options('/students', (req, res) => {
// 设置允许的请求源
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5173')
// 设置允许的请求方式
res.setHeader('Access-Control-Allow-methods', 'GET, POST')
// 设置允许的请求头
res.setHeader('Access-Control-Allow-Headers', 'token')
// 设置预检请求的缓存时间(可选)
res.setHeader('Access-Control-Max-Age', 7200)
res.send()
})
// 处理实际请求
app.get('/students', (req, res) => {
// 设置允许的请求源
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5173')
// 设置自定义响应头
res.setHeader('abc', '123')
// 设置允许暴露给客户端的响应头
res.setHeader('Access-Control-Expose-Headers', 'abc')
res.send(students)
})
- JSONP
VUE
项目中可以使用反向代理
将域名发送给本地服务器,由本地服务器去请求真实的服务器。
原理:同源策略是浏览器的保护机制,而服务器之间不存在
vue2
中,在vue.config.js
中配置
devServer: {
// 是否使用反向代理
// proxy: false,
proxy: {
'/api': {
target: 'http://127.0.0.1:8099', // 目标地址
changeOrigin: true, // 是否允许跨域
pathRewrite: {
// 重写,使用‘/autodts’代理‘http://10.234.99.80/autodts’
'^/api': ''
}
}
}
},
vue3
中,vite.config.js
中配置
server: {
proxy: {
'/api': {
target: 'http://127.0.0.1:8099', // 目标服务器地址
changeOrigin: true, // 是否改变源地址
rewrite: (path) => path.replace(/^\/api/, ''), // 重写路径
// 可以配置更多选项,如 logLevel, timeout 等
},
},
},
正向代理与反向代理
正向代理:代理客户端(浏览器)去请求客户端无法访问目标服务器资源, 目标服务器是不知道客户端的存在的
常见的: 开发环境配置的代理 / 翻墙工具
反向代理:代理对目标服务器来受理客户端的请求, 并转发给目标服务器处理, 客户端不用知道目标服务器的存在
常见的: 生产环境打包后的nginx
/ 百度用来做负载均衡的nginx
从输入url
到浏览器渲染出页面的整个过程
1.url
解析,浏览器先判断输入的是一个合法url
,还是一个待搜索的关键字
2.DNS
解析,浏览器会将输入的域名转换成IP
,通过IP
地址找到提供内容的服务器
3.TCP
连接,客户端会通过TCP
三次握手机制与服务器建立连接,如果是HTTPS
协议,则会多一步TLS
握手,建立加密的通信隧道.
4.客户端发送请求报文
5.服务器返回响应报文
6.四次挥手断开TCP
链接
7.解析渲染页面
浏览器渲染页面大致分为以下五步:
- 解析
HTML
代码,构建DOM
树. - 解析
CSS
代码,构建CSSOM
树 - 合并
DOM
和CSSOM
,构建渲染树(Render Tree
) - 重排:计算元素位置和尺寸等几何信息
- 重绘:绘制页面像素信息
- 浏览器会将各层的信息发送给
GPU
,开始渲染页面
三次握手和四次挥手
Seq
(序号)
ACK
(确认号): 确认序号有效
SYN
(标志位): 建立一个新链接
FIN
(标志位): 断开一个链接
三次握手:
客户端发送一个带有SYN
标示的报文请求建立连接
服务器返回一个带有SYN/ACK
标识的报文同意建立连接
客户端最后发送一个带有ACK
标识的报文来确认建立连接
四次挥手:
客户端发送一段带有FIN
标识的报文请求断开连接
服务器返回一段带有ACK
标识的报文表示收到请求
服务器再次返回一段带有FIN
标识的报文表示准备完毕,可以断开连接
客户端发送一段带有ACK
标识的报文确认断开连接
浏览器的缓存策略
强缓存
强缓存:直接使用浏览器缓存中的内容,不向服务器发送请求
实现:通过在请求头配置expires
或Cache-Control
通过expires
设置的是一个绝对时间,在此时间之前不会向服务器请求资源
通过Cache-Control
:max-age=3600
设置的是一个相对时间,浏览器会记录请求资源的时间点,max-age=3600
表示3600秒内不会再向服务器请求资源,而是使用浏览器中的缓存。
no-cache与no-store
no-cache
会绕过浏览器,我们为资源设置了no-cache
后,每次请求资源都不会去询问浏览器缓存,而是直接去询问服务器该资源是否过期。
no-store
是指不使用任何缓存策略,浏览器和服务器都不会缓存,每次请求都直接从服务器获取资源。
协商缓存
协商缓存(Etag):浏览器与服务器合作之下的缓存策略。
请求的资源通过资源标识与服务器协商比对,协商成功,服务器返回304状态码,浏览器从本地加载。协商缓存需要用到 Etag
字段与 if-none-match
,Etag
是 HTTP
响应头中的字段,Etag
的值是根据资源内容编码生成的一段字符串(资源标识),内容不同就会生成不同的Etag
。
再次发起请求时,请求头会带有if-none-match
字段,值为上一次响应的 Etag
(没有则不会携带)。
静态的html页面设置http缓存
通过HTTP
的META
设置cache-control
<meta http-equiv="Cache-Control" content="no-cache" />
如果不想命中协商缓存与强缓存,win
系统可以直接 ctrl + f5