JWT 重点讲解
文章目录
- JWT 重点讲解
- 1. JWT 是什么
- 2. JWT 的组成
- 2.1 第一部分 HEADER
- 2.2 第二部分 PAYLOAD
- 2.3 第三部分 SIGNATURE
- 3. JWT 在线生成与解析
- 4. JWT 的特点
- 4.1 无状态
- 4.2 可自定义
- 4.3 扩展性强
- 4.4 调试性好
- 4.5 安全性取决于密钥管理
- 4.6 无法撤销
- 4.7 需要缓存到客户端(需要传输给客户端)
- 4.8 载荷大小有限制
- 5. JWT 的优缺点
- 5.1 优点
- 5.2 缺点
- 6. JWT 实践
- 6.1 一次性验证
- 6.2 JWT 令牌登录
- 6.3 JWT 工具类
- 7. JWT 避坑指南
- 7.1 Redis 校验实现令牌泄露保护(Redis 处理泄露的 JWT )
- 7.2 临检 JWT 限制敏感操作
- 7.3 异常 JWT 监控判断:超频识别与限制
- 7.4 地域检查判断 JWT 泄露
- 7.5 客户端检查判断 JWT 泄露
- 7.6 JWT 令牌泄露预防:限时、限数、限频
- 8. JWT 常见面试题
- 8.1 什么是 JWT ?解释一下它的结构
- 8.2 JWT 优点有哪些?它与传统的 session-based 身份验证相比有什么优缺点?
- 8.3 在 JWT 的结构中,分别有哪些部分?每个部分的作用是什么?
- 8.4 JWT 如何工作?从开始到验证过程的完整流程是怎样的?
- 8.5 什么是 JWT 的签名?为什么需要对 JWT 进行签名?如何验证 JWT 的签名?
- 8.6 什么是 JWT 的令牌刷新?为什么需要这个功能?
- 8.7 JWT 是否加密?如果是,加密的部分是哪些?如果不是,那么它如何保证数据安全性?
- 8.8 在 JWT 中,如何处理 Token 过期的问题?有哪些方法可以处理?
- 8.9 JWT 和 OAuth2.0 有什么关系?它们之间有什么区别?
- 8.10 JWT 在什么场景下使用较为合适?它的局限性是什么?
- 8.8 在 JWT 中,如何处理 Token 过期的问题?有哪些方法可以处理?
- 8.9 JWT 和 OAuth2.0 有什么关系?它们之间有什么区别?
- 8.10 JWT 在什么场景下使用较为合适?它的局限性是什么?
1. JWT 是什么
官网:JSON Web Tokens - jwt.io
- JSON Web Token Introduction - jwt.io
JSON Web Token,简称 JWT,读音是 [d3pt] (jot 的发音),是一个基于 RFC 7519 的开放数据标准,它定义了一种宽松且紧凑的数据组合方式。其作用是 JWT 是一种加密后数据载体,可在各应用之间进行数据传输。
而传递的数据在“加密之前”,就是 JSON 字符串,自然也就可以传递“对象”
你也可以理解为,“一段 JSON 字符串”,浓缩后的数据
推荐学习视频:JWT_哔哩哔哩_bilibili
这是一个常见的登录逻辑,原本我们传统的 Cookie-Session 机制,用户登录成功后,之后携带 Cookie 中的 JSESSIONID 去访问服务器的会话记录,而 JWT 机制的话,则是登录成功后,返回一个 JWT 字符串,之后携带这个 JWT 就可以去访问其他接口了。
JWT 和 JSESSIONID 都可以说是访问令牌 Token,但 JSESSIONID 是访问会话记录,而 JWT 则本身就是数据!
但这也是对 JWT 的粗浅认知,接下来才是重头戏~
2. JWT 的组成
例子:
eyJhbGciOiJIUzI1NiJ9
.eyJqdGkiOiI0YWU1MDA2ZjAxNzU0NmM4ODE1NGNlNWZhMmQ4ODMwNCIsInN1YiI6IntcbiAgICBcImlkXCI6IDVcbn0iLCJpc3MiOiJzZyIsImlhdCI6MTcwODQxNzI4OSwiZXhwIjoxNzA4NTAzNjg5fQ
.EJXUxVDBcTHCBLrvrS_B40vgttlwZK2s1lB87FEjKNI
这就是一个 JWT
2.1 第一部分 HEADER
eyJhbGciOiJIUzI1NiJ9
是两个信息:
- alg:类型(JWT)
- typ:加密算法(HS256)
一般很固定就是这俩(除非设置为其他的)
{
"alg": "HS256",
"typ": "JWT"
}
使用 Base64 加密,构成 JWT 第一部分:HEADER
eyJhbGciOiJIUzI1NiJ9
2.2 第二部分 PAYLOAD
即载荷(也是 JSON 格式),有两种:
-
标准载荷(建议使用)
-
自定义载荷
可以是任何信息(一个键值对集合,Java 中就是个 Map,只不过这个 Map 要以某种特殊的形式存在于 JWT中),可以添加用户的相关消息等等~
可以理解为(标准载荷的一个属性是自定义载荷):
{ "data": [ {"k1": v1}, {"k2": v2} ], "exp": 1777777777, "iss": "macaku" // ... }
我的习惯是,将业务数据,转化为 JSON 作为 sub 的值,然后获取 sub 的值就行了~
- 机制就在这,爱咋玩咋玩
但是这也与我的另一个习惯相关,就是 JWT 存的一般是 ID 之类的不带具体信息的数据,说是“SubObject”也没问题,这样我感觉用法可以跟灵活,也防止敏感信息泄露,之后总结再来看这个会更清楚!
使用 Base64 加密,构成 JWT 第二部分:PAYLOAD
eyJqdGkiOiI0YWU1MDA2ZjAxNzU0NmM4ODE1NGNlNWZhMmQ4ODMwNCIsInN1YiI6IntcbiAgICBcImlkXCI6IDVcbn0iLCJpc3MiOiJzZyIsImlhdCI6MTcwODQxNzI4OSwiZXhwIjoxNzA4NTAzNjg5fQ
2.3 第三部分 SIGNATURE
即签名,算法如下:
signature = HMACSHA256(header.payload, secret)
其中
-
HMACSHA256
- 就是 HEADER 里的那个加密算法
-
header.payload 就是前两个部分
- eyJhbGciOiJIUzI1NiJ9
.eyJqdGkiOiI0YWU1MDA2ZjAxNzU0NmM4ODE1NGNlNWZhMmQ4ODMwNCIsInN1YiI6IntcbiAgICBcImlkXCI6IDVcbn0iLCJpc3MiOiJzZyIsImlhdCI6MTcwODQxNzI4OSwiZXhwIjoxNzA4NTAzNjg5fQ
- eyJhbGciOiJIUzI1NiJ9
-
secret
- 是服务器必须自行保存好的密钥
有 secret 不代表,解密不了,因为主要数据是 payload,有没有 secret 压根就不影响信息暴露。
其作用就是配合 signature
- 如果 header.payload 与 secret 加密后得到 signature,则说明这个 JWT 是值得信赖的,是服务器颁布的,避免伪造 JWT~
- ”是我颁布的“ 并且没有过期,则校验通过~
算出来的字符串用 Base 64 加密后构成第三部分:SIGNATURE
EJXUxVDBcTHCBLrvrS_B40vgttlwZK2s1lB87FEjKNI
3. JWT 在线生成与解析
JWT Token在线编码生成 - ToolTT在线工具箱
JWT Token在线解析解码 - ToolTT在线工具箱
- 不到 secret 也能解析
{
"data": [
{
"tooltt": "https://tooltt.com"
},
{
"username": "mms"
},
{
"gender": "boy"
}
],
"iat": 1708450751,
"exp": 1709135999,
"aud": "all",
"iss": "mms",
"sub": "{\"id\":1}"
}
4. JWT 的特点
4.1 无状态
JWT 一旦生成就是固定的,本身就是数据,并且无需在服务器存储
这让我想起《斗罗大陆》,“武魂殿会发给非武魂殿所属,但是被武魂殿认可的强者1块“教皇令”,见到此令就如同见到教皇亲临,拥有长老的权力,可见其效力之大。”
🤣🤣🤣
谁拿着 JWT ,只要这个 JWT 是我通过鉴定是我颁布的,那我就认定这个人。
这并不会在服务器保存什么”登录状态“之类的会话,来证明 JWT 是什么或者有效
- 有缓存也只是为了提高效率罢了
”时效性“不代表状态,是 JWT 提供的机制罢了,其实照样能解析,但是这个的存在,给 JWT 提供了有效期的特点
因为是固定的,那么是一定能解析出来的,并且解析出来的东西也是固定的,而不是因为某个状态,不能用啦,比如 Cookie-Session 机制,要是服务器把会话删了,Cookie 连根毛都不能兑换。
当然,也可以”打破无状态性“,自定义业务场景咯,例如 JWT 黑名单等等…
- 但是 JWT 仍然可以解析,只不过对令牌的校验逻辑不仅仅是 ”是我颁布的就行“
4.2 可自定义
JWT 的载荷是可以自定义的,灵活度提高
4.3 扩展性强
JWT 有一套标准规范,因此容易在不同平台和语言之间共享和解析
- (例如如果第三方登录,可以把平台 A 的 JWT 给平台 B,解析后校验,用户则在平台 B 登录,生成平台 B 的 JWT)
- 微服务架构,少不了多语言开发同个项目
4.4 调试性好
由于 JWT 的内容是以 Base64 编码后的字符串形式存在的,因此非常容易进行调试和分析(结构明了,解密简单)
4.5 安全性取决于密钥管理
密钥丢了,别人就可以伪造 JWT,威胁安全性
JWT 的安全性取决于密钥的管理。如果密钥被泄露或者被不当管理,那么 JWT 将会受到攻击。因此,在使用 JWT 时,一定要注意密钥的管理,包括生成、存储、更新、分发等等。
4.6 无法撤销
一旦生成,就是固定的字符串,要刷新也是换个新的,而不是让这个字符串转为另一个状态对应另一份数据!
4.7 需要缓存到客户端(需要传输给客户端)
JWT 包含用户信息和权限信息,一般需要在客户端缓存,要防止被窃取。
时间太久,很容易被别人拿到 JWT,从而干坏事,所以 JWT 引入时效性~
4.8 载荷大小有限制
由于 JWT 需要进行网络传输,对载荷大小有限制,不建议超过 1KB,会很影响性能
前面提到的 JWT 存 ID 之类的不带具体信息的数据,
载荷大小有限制 也是 一部分原因,
避免暴露敏感信息也是 一个,
无状态性和无法撤销 也是一个,如果用户信息有变动,JWT 的无状态性也代表这个消息可能更新不及时,且无法更新,只能刷新令牌了,还要让前端接下来请求换个 JWT,还不如存个不变的 ID,然后查服务器的缓存和数据库~
- 没有打破无状态性,因为这里还是以”是我颁布的“为 JWT 的校验逻辑
5. JWT 的优缺点
5.1 优点
- 无状态:
- JWT 本身不需要存储在服务器上,因此可以实现无状态的身份验证和授权
- 可扩展性
- JWT 的载荷可以自定义,因此可以根据需求添加任意信息
- 可靠性:
- JWT 使用数字签名来保证安全性,因此具有可靠性
- 跨平台性:
- JWT 支持多种编程语言和操作系统,因此具有跨平台性
- 高效性
- 由于 JWT 不需要查询数据库,因此具有高效性
5.2 缺点
- 安全性取决于密钥管理:
- JWT 的安全性取决于密钥的管理,如果密钥被泄露或者被不当管理,那么 JWT 将会受到攻击。
- 无法撤销令牌:
- 由于 JWT 是无状态的,一旦JT被签发,就无法撤销。
- 需要传输到客户端:
- 由于 JWT 包含了用户信息和授权信息,因此 JWT 需要传输到客户端,这意味着 JWT 有被攻击者窃取的风险。
- 载荷大小有限制:
- 由于 JWT 需要传输到客户端,因此载荷大小也有限制,差不多就十个左右的键值对。
6. JWT 实践
JSON Web Token Libraries - jwt.io
- 大部分的业务逻辑去遵守 JWT 规范,用 JWT 官方提供的接口方便开发
找个库去用即可,我选择的是:
<!--jjwt-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.64</version>
</dependency>
6.1 一次性验证
用户注册成功后发一份激活邮件或者其他业务需要邮箱激活操作,都是可以使用 JWT。
原因:
- JWT 时效性:
- 让该链接具有时效性(比如约定2小时内激活)
- JWT 不可篡改性(signature的保证):
- 防止篡改以激活其他账户
6.2 JWT 令牌登录
就是前面说的,见到这个令牌就相当于见到用户~
也是JWT被诟病最多的地方,因为]WT令牌存在各种不安全。
- JWT令牌存储与客户端,容易泄露并被伪造身份搞破坏。
- JWT 被签发,就无法撤销,当破坏在进行时,后端无法马上禁止。
上面问题可通过监控异常 JWT 访问,设置黑名单+强制下线等方式尽量避免损失。
6.3 JWT 工具类
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.11</version>
</dependency>
据实际进行代码调整~
/**
* JWT工具类
*/
@Slf4j
public class JwtUtil {
public static final String JWT_HEADER = "Token";
//设置秘钥明文
private static final String JWT_KEY = SpringUtil.getProperty("key.jwt");
private static final String applicationName = SpringUtil.getProperty("spring.application.name");
public static final Long JWT_TTL = 1L; // 一天有效期
public static final Long JWT_MAP_TTL = 6L; // 六小时
public static final TimeUnit JWT_TTL_UNIT = TimeUnit.DAYS;
public static final TimeUnit JWT_MAP_TTL_UNIT = TimeUnit.HOURS;
public static final String JWT_LOGIN_WX_USER = "jwtLoginWxUser:";
public static final String JWT_LOGIN_EMAIL_USER = "jwtLoginEmailUser:";
public static final String JWT_RAW_DATA_MAP = "jwtRawDataMap:";
public static String getUUID(){
String token = UUID.randomUUID().toString().replaceAll("-", "");
return token;
}
/**
* 生成jwt
* @param subject token中要存放的数据(json格式)
* @return
*/
public static String createJWT(String subject) {
JwtBuilder builder = getJwtBuilder(subject, null, getUUID(), null);// 设置过期时间
return builder.compact();
}
/**
* 生成jwt
* @param subject token中要存放的数据(json格式)
* @param ttlMillis token超时时间
* @return
*/
public static String createJWT(String subject, Long ttlMillis, TimeUnit timeUnit) {
JwtBuilder builder = getJwtBuilder(subject, ttlMillis, getUUID(), timeUnit);// 设置过期时间
return builder.compact();
}
private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid, TimeUnit timeUnit) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
SecretKey secretKey = generalKey();
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
if (Objects.isNull(ttlMillis) || Objects.isNull(timeUnit)) { // 只有其中一个也等于没有
ttlMillis = JWT_TTL_UNIT.toMillis(JwtUtil.JWT_TTL);
} else {
ttlMillis = timeUnit.toMillis(ttlMillis);
}
long expMillis = nowMillis + ttlMillis;
Date expDate = new Date(expMillis);
return Jwts.builder()
// .setClaims() // 设置自定义载荷
.setId(uuid) //唯一的ID
.setSubject(subject) // 主题 可以是JSON数据
.setIssuer(applicationName) // 签发者
.setIssuedAt(now) // 签发时间
.signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥
.setExpiration(expDate); // 失效时间
}
/**
* 创建token
* @param id
* @param subject
* @param ttlMillis
* @return
*/
public static String createJWT(String id, String subject, Long ttlMillis, TimeUnit timeUnit) {
JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id, timeUnit);// 设置过期时间
return builder.compact();
}
/**
* 生成加密后的秘钥 secretKey
* @return
*/
public static SecretKey generalKey() {
byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
/**
* 解析
*
* @param jwt
* @return
* @throws Exception
*/
public static Claims parseJWT(String jwt) {
SecretKey secretKey = generalKey();
return Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody(); // 获得载荷
}
/**
* 解析
*
* @param jwt
* @return
* @throws Exception
*/
public static String parseJWTRawData(String jwt) {
return parseJWT(jwt).getSubject();
}
public static <T> T getJwtKeyValue(String jwt, String key, Class<T> clazz) {
return parseJWT(jwt).get(key, clazz);
}
public static Date getExpiredDate(String jwt) {
Date result = null;
try {
result = parseJWT(jwt).getExpiration();
} catch (ExpiredJwtException e) {
result = e.getClaims().getExpiration();
}
return result;
}
public static String refreshToken(String jwt) {
return createJWT(parseJWTRawData(jwt));
}
// 过期的话 parseJWT(jwt)会抛异常,也就是 “没抛异常能解析成功就是校验成功”,但是异常 ExpiredJwtException 的 getClaims 方法能获取到 payload
public static boolean isTokenExpired(String jwt) {
return getExpiredDate(jwt).before(new Date());
}
public static boolean validateToken(String jwt) {
try {
parseJWT(jwt);
} catch (ExpiredJwtException e) {
return false;
}
return true;
}
}
7. JWT 避坑指南
JWT 无非就是泄露问题~
- 毕竟它是无状态的,见到令牌就是见到用户
7.1 Redis 校验实现令牌泄露保护(Redis 处理泄露的 JWT )
因为 JWT 是无状态的,当 JWT 令牌颁发后,在有效时间内,是无法进行销毁,所以就存在很大隐患:令牌泄露
避坑:
- 颁发 JWT 令牌时,在 Redis 中也缓存一份,当判定某个 JWT 泄露了,立即移除 Redis 中的 JWT
- 当接口发起请求时,强制用户重新进行身份验证,直至验证成功。
7.2 临检 JWT 限制敏感操作
因为 JWT 是无状态的,泄露可能性大,进行一些敏感操作时需要进行临检操作。
避坑:
- 强制重新检查用户身份,生成一个新的短时的 JWT 去进行敏感操作(当然,这个短时 JWT 与登录用户的 JWT 应该不同!并且登录用户的 JWT 不能用于进行敏感操作),判断操作者是用户本人
7.3 异常 JWT 监控判断:超频识别与限制
当 JWT 令牌被盗取,一般会出现高频次的系统访问。针对这种情况,监控用户端在单位时间内的请求次数,当单位时间内的请求次数超出预定阈值值,则判定该用户 JWT 令牌异常。
避坑:
- 当判断 JWT 令牌异常,直接进行限制(比如:IP限流,JWT黑名单等)。
7.4 地域检查判断 JWT 泄露
一般用户活动范围是固定,意味着 JWT 客户端访问 IP 相对固定,JWT 泄露之后,可能会先异地登录的情况。
避坑:
- 对 JWT 进行异地访问检查,有效时间内,IP 频繁变动或地域变动范围很大可判断为 JWT 泄露。
7.5 客户端检查判断 JWT 泄露
如果在很多设备上登录(请求携带不同设备机械码),很有可能,这个 JWT 泄露了
避坑:
- 在 JWT 中保存生效的机器码可以是哪些(范围限制)
- 在服务器保存这个 JWT 绑定的机械码(范围限制)
- 限制 JWT 只能在 n 个不同设备上登录(次数限制)
7.6 JWT 令牌泄露预防:限时、限数、限频
JWT令牌泄露是无法避免,但是我们可以进行泄露识别,做好泄露后补救保证系统安全
避坑:
- 对客户端进行合理限制,比如限制每个客户端的 JWT 令牌数量、访问频率、JWT令牌时效等,以降低 JWT令牌泄露的风险。
- 减少JWT令牌时效也可以减少滥用时间~
8. JWT 常见面试题
8.1 什么是 JWT ?解释一下它的结构
JWT 是一种开放标准,用于在网络上安全地传输信息。它由三部分组成:头部、载荷和签名。头部包含令牌的元数据,载荷包含实际的信息(例如用户ID、角色等),签名用于验证令牌是否被篡改。
8.2 JWT 优点有哪些?它与传统的 session-based 身份验证相比有什么优缺点?
JWT 的优点包括无状态、可扩展、跨语言、易于实现和良好的安全性。相比之下,传统的 session-based 身份验证需要在服务端维护会话状态,使得服务端的负载更高,并且不适用于分布式系统
JWT 还不会出现 CSRF 漏洞
- CSRF 攻击和防御 - Web 安全常识_哔哩哔哩_bilibili
- 主要是,进入攻击者的页面是没有携带指定 JWT 令牌,并且一般 JWT 会习惯设置在请求头上~
8.3 在 JWT 的结构中,分别有哪些部分?每个部分的作用是什么?
JWT 的结构由三部分组成:头部、载荷和签名。头部包含令牌类型和算法,载荷包含实际的信息,签名由头部、载荷和密钥生成。
8.4 JWT 如何工作?从开始到验证过程的完整流程是怎样的?
JWT的工作流程分为三个步骤:生成令牌、发送令牌、验证令牌。在生成令牌时,服务端使用密钥对头部和载荷进行签名。在发送令牌时,将令牌发送给客户端。在验证令牌时,客户端从令牌中解析出头部和载荷,并使用相同的密钥验证签名。
可能包含第四个步骤:刷新令牌,当发觉令牌快过期了,生成新的令牌,发送新的令牌给客户端,之后客户端发的是新的令牌,验证令牌(由于无状态性,旧令牌依旧有效,除非自定义业务使其有了状态)
8.5 什么是 JWT 的签名?为什么需要对 JWT 进行签名?如何验证 JWT 的签名?
JWT 的签名是由头部、载荷和密钥生成的,用于验证令牌是否被篡改。签名使用HMAC算法或RSA算法生成。在验证JWT的签名时,客户端使用相同的密钥和算法生成签名,并将生成的签名与令牌中的签名进行比较。
8.6 什么是 JWT 的令牌刷新?为什么需要这个功能?
令牌刷新是一种机制,用于解决 JWT 过期后需要重新登录的问题。在令牌刷新中,服务端生成新的 JWT,并将其发送给客户端。客户端使用新的 JWT 替换旧的 JWT,从而延长令牌的有效期。
8.7 JWT 是否加密?如果是,加密的部分是哪些?如果不是,那么它如何保证数据安全性?
JWT 本身并不加密(虽然说 Base64 加密,但那只不过是浓缩罢了,一点都不秘密),而是使用签名来保证数据的完整性和认证信息的可靠性(通过 header 提供的加密算法,计算 signature 就涉及加密)
但可以在载荷中包含敏感信息,为了保护这些信息,可以使用 JWE (SON Web Encryption)对载荷进行加密。如果不加密,则需要在生成 JWT 时确保不在载荷中包含敏感信息。
8.8 在 JWT 中,如何处理 Token 过期的问题?有哪些方法可以处理?
JWT 过期后,客户端需要重新获取新的 JWT 。(过期也能获得payload的,通过抛出的异常 ExpiredJwtException 的 getClaims 方法能获取到 payload)
自定义refresh token机制来解决快要过期的问题。
8.9 JWT 和 OAuth2.0 有什么关系?它们之间有什么区别?
JWT 和 OAuth2.0 都是用于身份验证和授权的开放标准。JWT 是一种身份验证机制,而 OAuth2.0 是一种授权机制。JWT 用于在不同的系统中安全地传输信息,OAuth2.0 用于授权第三方应用程序访问受保护的资源。
8.10 JWT 在什么场景下使用较为合适?它的局限性是什么?
JWT 在单体应用或微服务架构中的使用比较合适。它的局限性包括无法撤销、令牌较大、无法处理并发等问题。
性和认证信息的可靠性(通过 header 提供的加密算法,计算 signature 就涉及加密)
但可以在载荷中包含敏感信息,为了保护这些信息,可以使用 JWE (SON Web Encryption)对载荷进行加密。如果不加密,则需要在生成 JWT 时确保不在载荷中包含敏感信息。
8.8 在 JWT 中,如何处理 Token 过期的问题?有哪些方法可以处理?
JWT 过期后,客户端需要重新获取新的 JWT 。(过期也能获得payload的,通过抛出的异常 ExpiredJwtException 的 getClaims 方法能获取到 payload)
自定义refresh token机制来解决快要过期的问题。
8.9 JWT 和 OAuth2.0 有什么关系?它们之间有什么区别?
JWT 和 OAuth2.0 都是用于身份验证和授权的开放标准。JWT 是一种身份验证机制,而 OAuth2.0 是一种授权机制。JWT 用于在不同的系统中安全地传输信息,OAuth2.0 用于授权第三方应用程序访问受保护的资源。
8.10 JWT 在什么场景下使用较为合适?它的局限性是什么?
JWT 在单体应用或微服务架构中的使用比较合适。它的局限性包括无法撤销、令牌较大、无法处理并发等问题。
适合去做“一次性验证”与“登录令牌”