JSON Web Token (JWT)的简单介绍、验证过程及令牌刷新思路
目录
一、JWT
1、什么是Jwt
2、为什么要使用Jwt
3、应用场景
4.Jwt的组成
4.1、Header
4.2、Payload
4.3、signature
二、Jwt验证过程
1、生成Jwt令牌
2、解析旧的Jwt
3、复制Jwt
4、Jwt有效时间测试
三、Jwt令牌刷新思路
1、配置JwtFilter过滤器
2、登录生成Jwt令牌
3、配置CorsFilter过滤器
4、Vuex存储Jwt令牌
5、修改main.js
6、配置axios请求响应头
前言:
随着前后端分离的发展,以及数据中心的建立,越来越多的公司会创建一个中心服务器,服务于各种产品线。而这些产品线上的产品,它们可能有着各种终端设备,包括但不仅限于浏览器、桌面应用、移动端应用、平板应用、甚至智能家居。
这些设备与中心服务器之间会进行http通信,一般来说,中心服务器至少承担着认证和授权的功能。例如登录:各种设备发送消息到中心服务器,然后中心服务器响应一个身份令牌,当这种结构出现后,就出现一个问题:它们之间还能使用传统的cookie方式传递令牌信息吗?
其实,也是可以的,因为cookie在传输中无非是一个消息头而已,只不过浏览器对这个消息头有特殊处理罢了。但浏览器之外的设备肯定不喜欢cookie,因为浏览器有着对cookie完善的管理机制,但是在其他设备上,就需要开发者自己手动处理了。
JWT 的出现就是为了解决这个问题!!!
一、JWT
1、什么是Jwt
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。是目前最流行的跨域身份验证解决方案;
RFC 7519:RFC 7519 - JSON Web Token (JWT)
2、为什么要使用Jwt
它要解决的问题,就是为多种终端设备,提供统一的、安全的令牌格式。因此,jwt只是一个令牌格式而已,你可以把它存储到cookie,也可以存储到localstorage,没有任何限制!同样的,对于传输,你可以使用任何传输方式来传输jwt,一般来说,我们会使用消息头header来传输它。
比如:当登录成功后,服务器可以给客户端响应一个Jwt。
HTTP/1.1 200 OK
...
set-cookie:token=jwt令牌
authorization:jwt令牌
...{..., token:jwt令牌}
可以看到,jwt令牌可以出现在响应的任何一个地方,客户端和服务器自行约定即可。
当然,它也可以出现在响应的多个地方,比如为了充分利用浏览器的 cookie,同时为了照顾其他设备,也可以让 jwt 出现在 set-cookie 和 authorization 或 body 中,尽管这会增加额外的传输量。
总之,Jwt的精髓在于去中心化,数据是保存在客户端的。
3、应用场景
- 认证:认证是JWT的最常用场景。只要用户完成登录,其随后的请求都会包含JWT,以允许用户访问经由当前JWT授权的路由、服务或者是资源。由于开销小且能够被简单应用在跨域访问上,JWT在分布式站点上所支持的单点登录(SSO)已经是当前它被广泛应用的一个特性。
- 信息交换:JWT是一种在各参与方之间安全传递信息的良好方法。由于JWT可以被签名(例:使用公钥/秘钥对),因而可用于确认发送者自称的身份。除此之外,由于signature使用header和payload进行计算,也可以验证内容没有被篡改。
JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
4.Jwt的组成
一个Jwt实际上就是一个字符串,它由三部分组成:
-
Header(头部)
-
Payload(载荷)
-
Signature(签名)
eyJhbGciOiJIUzI1NiJ9.
eyJzdWIiOiJ7fSIsImlzcyI6InpraW5nIiwiZXhwIjoxNTYyODUwMjM3LCJpYXQiOjE1NjI4NDg0MzcsImp0aSI6ImM5OWEyMzRmMDc4NzQyZWE4YjlmYThlYmYzY2VhNjBlIiwidXNlcm5hbWUiOiJ6c3MifQ.
WUfqhFTeGzUZCpCfz5eeEpBXBZ8-lYg1htp-t7wD3I4
它是一个很长的字符串因此,中间用点(.)分隔成三个部分。
注意,Jwt 内部是没有换行的,这里只是为了便于展示,将它写成了几行。
4.1、Header
典型的JWT header包含两个部分:
-
typ(type)属性,用来标识整个token字符串是一个JWT字符串,即JWT。
-
alg(algorithm)属性,用来说明这个JWT签发的时候所使用的签名和摘要算法,比如HMAC SHA256或者RSA。
{"alg": "HS256","typ": "JWT"
}
4.2、Payload
JWT token的第二部分是包含了声明的payload,声明(要求)是一个实体的表述加上额外信息,一共有三种形式的声明:注册、公有和私有;
- 注册声明
它的json结构实际上是对JWT要传递的数据的一组声明,这些声明被JWT标准称为claims,它的一个属性值对其实就是一个claim(要求),每一个claim的都代表特定的含义和作用。
{"iss":"发行者","iat":"发布时间","exp":"到期时间","sub":"主题","aud":"听众","nbf":"在此之前不可用","jti":"JWT ID"
}
属性 | 说明 |
---|---|
iss(Issuser) | 代表这个JWT的签发主体 |
sub(Subject) | 代表这个JWT的主体,即它的所有人 |
aud(Audience) | 代表这个JWT的接收对象 |
exp(Expiration time) | 是一个时间戳,代表这个JWT的过期时间 |
nbf(Not Before) | 是一个时间戳,代表这个JWT生效的开始时间,意味着在这个时间之前验证JWT是会失败的 |
iat(Issued at) | 是一个时间戳,代表这个JWT的签发时间 |
jti(JWT ID) | 是JWT的唯一标识 |
- 公有声明
公有声明可以加入任何信息,一般会添加用户相关信息或者业务需要的信息,但不建议添加敏感信息,因为该部分会在客户端解密。
- 私有声明
私有声明是提供者和使用者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密,基本等同于明文信息。
如果把JWT用于认证, 那么JWT标准内规定的几个claim就足够用了,甚至只需要其中一两个就可以了,假如想往JWT里多存一些用户业务信息,比如角色和用户名等,这倒是可以用私有声明来添加。
4.3、signature
JWT的第三部分是签名信息,Signature由三部分组成:
-
header(base64加密后)
-
payload(base64加密后)
-
secret (盐)
签名需要将base64加密后的header和payload使用.
连接,然后通过header所使用的加密方式进行加盐(secret)组合加密,产生了jwt的第三部分。以使用HMAC SHA256算法为例;
按照前面alg可用值的说明,HS256其实包含的是两种算法:HMAC算法和SHA256算法,前者用于生成摘要,后者用于对摘要进行数字签名。这两个算法也可以用HMAC SHA256来统称;
HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
签名是用于验证消息在传递过程中有没有被更改,并且,对于使用私钥签名的token,它还可以验证JWT的发送方是否为它所称的发送方。
算法不同,签名结果不同。
二、Jwt验证过程
可将绑定的资源中src(ElementUI之Jwt)目录下的JwtUtils.java
和JwtDemo.java
导入到项目中的util包下:
1、生成Jwt令牌
//定义私有声明
Map<String, Object> claims = new HashMap<String, Object>();
claims.put("username", "zss");
claims.put("age", 18);
//根据私有声明和JWT的token有效时间生成JWT
String jwt = JwtUtils.createJwt(claims, JwtUtils.JWT_WEB_TTL);//获取JWT中的声明信息,包括:私有声明和标准声明
Claims parseJwt = JwtUtils.parseJwt(jwt);
for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {System.out.println(entry.getKey() + "=" + entry.getValue());
}
//获取token令牌的签发时间
Date d1 = parseJwt.getIssuedAt();
//获取token令牌的过期时间
Date d2 = parseJwt.getExpiration();
System.out.println("令牌签发时间:" + sdf.format(d1));
System.out.println("令牌过期时间:" + sdf.format(d2));
2、解析旧的Jwt
解析旧的JWT。如果超过JWT本身定义的过期时间,则直接抛出ExpiredJwtException
//旧的JWT令牌
String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjM2NzY0NDQsImlhdCI6MTU2MzY3NDY0NCwiYWdlIjoxOCwianRpIjoiMzE5MmYxOTg4NzFkNGVkZWIyMzU0MmY3NWVhMWI5NDciLCJ1c2VybmFtZSI6InpzcyJ92.4VnkdvGNNe8U1EiKaLz7h6bOJkVGSGtfqojcP_y-0Cc";
Claims parseJwt = JwtUtils.parseJwt(oldJwt);
for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {System.out.println(entry.getKey() + "=" + entry.getValue());
}
Date d1 = parseJwt.getIssuedAt();
Date d2 = parseJwt.getExpiration();
System.out.println("令牌签发时间:" + sdf.format(d1));
System.out.println("令牌过期时间:" + sdf.format(d2));
3、复制Jwt
模拟Session功能(Tomcat默认session过期时间:30分钟)。当有访问的情况下,自动延长jwt中的token令牌过期时间,在原有时间上+30秒;
String oldJwt = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjM2NzUzMDAsImlhdCI6MTU2MzY3MzUwMCwiYWdlIjoxOCwianRpIjoiYjY5MmE5ZjZkMGZhNDMyN2I1YWY2NTI5OGMzMjQ5MTYiLCJ1c2VybmFtZSI6InpzcyJ9.asHGMPFKURMLnooK29abAuKEdLOHBycAuTovNuGQio0";
String jwt = JwtUtils.copyJwt(oldJwt, JwtUtils.JWT_WEB_TTL);
Claims parseJwt = JwtUtils.parseJwt(jwt);
for (Map.Entry<String, Object> entry : parseJwt.entrySet()) {System.out.println(entry.getKey() + "=" + entry.getValue());
}
Date d1 = parseJwt.getIssuedAt();
Date d2 = parseJwt.getExpiration();
System.out.println("令牌签发时间:" + sdf.format(d1));
System.out.println("令牌过期时间:" + sdf.format(d2));
4、Jwt有效时间测试
生成新的Jwt令牌,设置令牌有效时间3秒钟,在3秒钟后再次解析Jwt令牌提示令牌已过期。
Map<String, Object> claims = new HashMap<String, Object>();
claims.put("username", "zss");
String jwt = JwtUtils.createJwt(claims, 3 * 1000L);
System.out.println(jwt);
Claims parseJwt = JwtUtils.parseJwt(jwt);
Date d1 = parseJwt.getIssuedAt();
Date d2 = parseJwt.getExpiration();
System.out.println("令牌签发时间:" + sdf.format(d1));
System.out.println("令牌过期时间:" + sdf.format(d2));
三、Jwt令牌刷新思路
使用ssm+vue+elementui实现jwt验证。
1、配置JwtFilter过滤器
导入JwtFilter.java
到utils包下,并注意配置顺序问题:CorsFilter
> JwtFilter
> SpringMVC核心控制器
<!-- JwtFilter -->
<filter><filter-name>jwtFilter</filter-name><filter-class>com.wsl.ssm.jwt.JwtFilter</filter-class>
</filter>
<filter-mapping><filter-name>jwtFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
2、登录生成Jwt令牌
在登录成功后,使用JwtUtil工具类生成JWT,并将Jwt令牌添加到响应头(response)中带到前端页面。在这里可以将用户对应用户基本信息和用户角色信息保存到私有claim中。
if(userVo.getUsername().equals("admin")&&userVo.getPassword().equals("123")){//私有要求claimMap<String,Object> json=new HashMap<String,Object>();json.put("username", userVo.getUsername());//生成JWT,并设置到response响应头中String jwt=JwtUtils.createJwt(json, JwtUtils.JWT_WEB_TTL);response.setHeader(JwtUtils.JWT_HEADER_KEY, jwt);return new JsonResponseBody<>("用户登陆成功!",true,0,null);
}else{return new JsonResponseBody<>("用户名或密码错误!",false,0,null);
}
3、配置CorsFilter过滤器
浏览器只能访问默认的响应头,例如:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma等,如果想让浏览器能访问到其他的响应头的话,需要在服务器上设置。在CorsFilter跨域过滤器的doFilter方法中配置其他响应头的支持。
//允许客户端发一个新的请求头jwt
httpResponse.setHeader("Access-Control-Allow-Headers","Origin,X-Requested-With, Content-Type, Accept, jwt");
//允许客户端处理一个新的响应头jwt
httpResponse.setHeader("Access-Control-Expose-Headers", "jwt");
4、Vuex存储Jwt令牌
使用vuex
保存后端服务器提交过来的Jwt
,分别在state、getters、mutation
中定义信息。
- state.js
export default {jwt:null }
- getters.js
export default {getJwt:(state)=>{return state.jwt;} }
- mutation.js
export default {setJwt:function (state, payload){state.jwt = payload.jwt;} }
5、修改main.js
解决axios从响应头获得jwt令牌并保存到vuex,通过修改main.js中的配置window.vm=new Vue({});获取Vue根实例对象。
window.vm = new Vue({el: '#app',router,store,components: { App },template: '<App/>'
})
6、配置axios请求响应头
在vue的http.js中配置axios的请求响应拦截器,用于存取Jwt,并将Jwt信息保存到Vuex中。
// 请求拦截器
axios.interceptors.request.use(function(config) {let jwt=window.vm.$store.getters.jwt;//console.log(jwt);if(jwt)config.headers['jwt']=jwt;return config;
}, function(error) {return Promise.reject(error);
});// 响应拦截器
axios.interceptors.response.use(function(response) {let jwt=response.headers['jwt'];if(jwt)window.vm.$store.commit('setJwt',{jwt:jwt});return response;
}, function(error) {return Promise.reject(error);
});
注:可通过使用vuex-along解决刷新state初始化问题。
相关文章:

JSON Web Token (JWT)的简单介绍、验证过程及令牌刷新思路
目录 一、JWT 1、什么是Jwt 2、为什么要使用Jwt 3、应用场景 4.Jwt的组成 4.1、Header 4.2、Payload 4.3、signature 二、Jwt验证过程 1、生成Jwt令牌 2、解析旧的Jwt 3、复制Jwt 4、Jwt有效时间测试 三、Jwt令牌刷新思路 1、配置JwtFilter过滤器 2、登录生成Jwt令…...

xxl-job入门
xxl-job , 定时任务 分布式 , 带来的问题的 解决方案 像之前 很多项目都用到定时任务, 但是如果要改为 分布式, 那么定时任务 就要用到 xxl-job 1.用户画像 拼多多,看了某个东西后,推荐类似东西, 做埋…...

100.【C语言】数据结构之二叉树的堆实现(顺序结构) 1
目录 1.顺序结构 2.示意图 编辑 从物理结构还原为逻辑结构的方法 3.父子节点编号的规律 4.顺序存储的前提条件 5.堆的简介 堆的定义 堆的两个重要性质 小根堆和大根堆 6.堆的插入 7.堆的实现及操作堆的函数 堆的结构体定义 堆初始化函数HeapInit 堆插入元素函…...
大模型 VS 大语言模型
最近很多朋友搞不懂大模型和大预言模型的区别,总是把大模型就认为是大语言模型。 今天就用这篇帖子做一个科普。 大模型 概念:大模型是指拥有超大规模参数(通常在十亿个以上)、复杂计算结构的机器学习模型。它通常能够处理海量数…...

Linux高阶——1117—TCP客户端服务端
目录 1、sock.h socket常用函数 网络初始化函数 首次响应函数 测试IO处理函数 获取时间函数 总代码 2、sock.c SOCKET() ACCEPT()——服务端使用这个函数等待客户端连接 CONNECT()——客户端使用这个函数连接服务端 BIND()——一般只有服务端使用 LISTEN()——服务端…...
【Qt】Qt 在main.cpp中使用tr()函数报错
1. 问题 Qt 在main.cpp中使用tr()报错。 error: tr was not declared in this scope2. 解决方法 main.cpp中注意如下: //添加头文件 #include <QObject>//添加QObject QObject::tr("Hello")3. 参考 Qt tr()函数不起效的小问题...
面向对象高级(5)接口
面向对象高级(5) 接口 接口就是规范,定义的是一组规则,体现了现实世界中“如果是...则必须能...”的思想。继承是一个"是不是"的is-a关系,而接口实现则是 "能不能"的has-a关系。 1、接口的定义格…...

uniapp发布android上架应用商店权限
先看效果: 实现原理: 一、利用uni.addInterceptor的拦截器,在一些调用系统权限前拦截,进行弹窗展示,监听确定取消实现业务逻辑。 二、弹窗是原生nativeObj进行drawRect绘制的 三、权限申请调用使用的 plus.android.…...

Centos Stream 9安装Jenkins-2.485 构建自动化项目步骤
官网:https://www.jenkins.io/ 1 下载 环境准备: 版本支持查询:https://pkg.jenkins.io/redhat-stable/ 安装JDK17:https://blog.csdn.net/qq_44870331/article/details/140784297 yum -y install epel-release wget upgradew…...

电路模型和电路定理(二)
电路元件 是电路中最基本的组成单元。 电阻元件:表示消耗电能的元件 电感元件:表示产生磁场,储存磁场能的元件 电容元件:表示产生电场,储存电场能量的元件 电压源和电流源:表示将其他形式的能量转变成…...

瑞佑液晶控制芯片RA6807系列介绍 (三)软件代码详解 Part.10(让PNG图片动起来)完结篇
RA6807是RA8876M的缩小版,具备RA8876M的所有功能,只将MCU控制接口进行缩减,仅保留SPI-3和I2C接口,其它功能基本相同。 该芯片最大可控制854x600的分辨率,内建64Mbits显存,多个图层,使用起来相当…...

Qt常用控件 按钮
文章目录 1. QAbstractButton 简介2. QPushButton2.1 例子1,设置按钮的图标2.2 例子2,设置按钮快捷键 3. QRadioButton3.1 介绍3.2 例子1,选择性别3.3 例子2,试试其他的信号3.3 例子3,分组 4. QCheckBox4.1 介绍4.2 例…...

MySQL学习/复习10视图/用户/权限/语言连接数据库
一、视图 1.1创建视图 1.2视图影响基表 1.3基表影响视图 1.4删除视图 1.5视图使用规则 二、数据库的用户 2.1mysql中的user表 注意事项:主机/用户名/密码/权限 2.2用户的创建 注意事项:设置密码与登录地点需谨慎 2.3删除用户 注意事项:% 2.4…...

vulfocus在线靶场:tomcat-pass-getshell 弱口令 速通手册
目录 一、启动环境,访问页面,并登录,账号密码都是tomcat 二、哥斯拉打war包,图解 三、上传war包,图解 四、访问我们直接url/木马文件名/木马文件.jsp,是否存在了 五、 哥斯拉测试连接结果success&…...

c#:winform调用bartender实现打印(学习整理笔记)
效果 学习路径 C# winform调用Bartender进行自定义打印、批量打印、检索文件夹中的模板_哔哩哔哩_bilibili 一、初始环境搭建见: c#:winform引入bartender-CSDN博客https://blog.csdn.net/weixin_46001736/article/details/143989473?sharetypeblogdetail&s…...
牛客题库 21738 牛牛与数组
牛牛与数组题目链接 题目大意 牛牛喜欢这样的数组: 1:长度为n 2:每一个数都在1到k之间 3:对于任意连续的两个数A,B,A<=B 与(A % B != 0) 两个条件至少成立一个请问一共有多少满足条件的数组,对 1 e 9 + 7 1e^9+7 1e9+7 取模 输入格式 输入两个整数 n , k n,k n,…...

探索PDFMiner:Python中的PDF解析利器
文章目录 **探索PDFMiner:Python中的PDF解析利器**1. 背景介绍:为何选择PDFMiner?2. PDFMiner是什么?3. 如何安装PDFMiner?4. 简单库函数使用方法4.1 提取文本4.2 获取页面布局信息4.3 提取表格数据4.4 提取图像 5. 应…...
掌握Go语言中的异常控制:panic、recover和defer的深度解析
掌握Go语言中的异常控制:panic、recover和defer的深度解析 在Go语言的编程世界中,异常处理是一个不可忽视的话题。Go语言提供了panic、recover和defer三个关键字来处理程序中的异常情况。本文将深入探讨这三个关键字的工作原理、使用场景和最佳实践,帮助读者在实际编程中更…...

云讷科技Kerloud无人飞车专利发布
云讷科技Kerloud无人飞车获得了“一种室内外两用的四旋翼无人飞车”的实用新型专利证书,作为科教社区第一款四旋翼飞车,这项技术结合了无人机和无人车的优势,提供了一种能够在多种环境下使用的多功能飞行器。 这项设计的优势如下ÿ…...

企业信息化-走进身份管理之搭建篇
一、身份管理是什么 我们先要弄懂统一身份管理到底是什么? 统一身份管理(Unified Identity Manager,UIM),身份管理(Identity Management,简称IDM),也被称为IAM&#…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...

C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
文章目录 一、开启慢查询日志,定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...