sa-token/sa-token-doc/plugin/jwt-extend.md

247 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 和 jwt 集成
本插件的作用是让 Sa-Token 和 jwt 做一个整合。
---
### 1、引入依赖
首先在项目已经引入 Sa-Token 的基础上,继续添加:
<!---------------------------- tabs:start ---------------------------->
<!-------- tab:Maven 方式 -------->
``` xml
<!-- Sa-Token 整合 jwt -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jwt</artifactId>
<version>${sa.top.version}</version>
</dependency>
```
<!-------- tab:Gradle 方式 -------->
``` gradle
// Sa-Token 整合 jwt
implementation 'cn.dev33:sa-token-jwt:${sa.top.version}'
```
<!---------------------------- tabs:end ---------------------------->
> 1. 注意: sa-token-jwt 显式依赖 hutool-jwt 5.7.14 版本,保险起见:你的项目中要么不引入 hutool要么引入版本 >= 5.7.14 的 hutool 版本。
> 2. hutool 5.8.13 和 5.8.14 版本下会出现类型转换问题,[关联issue](https://gitee.com/dromara/sa-token/issues/I6L429)。
### 2、配置秘钥
`application.yml` 配置文件中配置 jwt 生成秘钥:
<!---------------------------- tabs:start ---------------------------->
<!------------- tab:yaml 风格 ------------->
``` yaml
sa-token:
# jwt秘钥
jwt-secret-key: asdasdasifhueuiwyurfewbfjsdafjk
```
<!------------- tab:properties 风格 ------------->
``` properties
# jwt秘钥
sa-token.jwt-secret-key: asdasdasifhueuiwyurfewbfjsdafjk
```
<!---------------------------- tabs:end ---------------------------->
注:为了安全起见请不要直接复制官网示例这个字符串(随便按几个字符就好了)
### 3、注入jwt实现
根据不同的整合规则,插件提供了三种不同的模式,你需要 **选择其中一种** 注入到你的项目中
<!------------------------------ tabs:start ------------------------------>
<!-- tab: Simple 简单模式 -->
Simple 模式Token 风格替换
``` java
@Configuration
public class SaTokenConfigure {
// Sa-Token 整合 jwt (Simple 简单模式)
@Bean
public StpLogic getStpLogicJwt() {
return new StpLogicJwtForSimple();
}
}
```
<!-- tab: Mixin 混入模式 -->
Mixin 模式:混入部分逻辑
``` java
@Configuration
public class SaTokenConfigure {
// Sa-Token 整合 jwt (Mixin 混入模式)
@Bean
public StpLogic getStpLogicJwt() {
return new StpLogicJwtForMixin();
}
}
```
<!-- tab: Stateless 无状态模式 -->
Stateless 模式:服务器完全无状态
``` java
@Configuration
public class SaTokenConfigure {
// Sa-Token 整合 jwt (Stateless 无状态模式)
@Bean
public StpLogic getStpLogicJwt() {
return new StpLogicJwtForStateless();
}
}
```
<!---------------------------- tabs:end ------------------------------>
### 4、开始使用
然后我们就可以像之前一样使用 Sa-Token 了
``` java
/**
* 登录测试
*/
@RestController
@RequestMapping("/acc/")
public class LoginController {
// 测试登录
@RequestMapping("login")
public SaResult login() {
StpUtil.login(10001);
return SaResult.ok("登录成功");
}
// 查询登录状态
@RequestMapping("isLogin")
public SaResult isLogin() {
return SaResult.ok("是否登录:" + StpUtil.isLogin());
}
// 测试注销
@RequestMapping("logout")
public SaResult logout() {
StpUtil.logout();
return SaResult.ok();
}
}
```
访问上述接口观察Token生成的样式
``` java
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbklkIjoiMTAwMDEiLCJybiI6IjZYYzgySzBHVWV3Uk5NTTl1dFdjbnpFZFZHTVNYd3JOIn0.F_7fbHsFsDZmckHlGDaBuwDotZwAjZ0HB14DRujQfOQ
```
### 5、不同模式策略对比
注入不同模式会让框架具有不同的行为策略,以下是三种模式的差异点(为方便叙述,以下比较以同时引入 jwt 与 Redis 作为前提):
| 功能点 | Simple 简单模式 | Mixin 混入模式 | Stateless 无状态模式 |
| :-------- | :-------- | :-------- | :-------- |
| Token风格 | jwt风格 | jwt风格 | jwt风格 |
| 登录数据存储 | Redis中存储 | Token中存储 | Token中存储 |
| Session存储 | Redis中存储 | Redis中存储 | 无Session |
| 注销下线 | 前后端双清数据 | 前后端双清数据 | 前端清除数据 |
| 踢人下线API | 支持 | 不支持 | 不支持 |
| 顶人下线API | 支持 | 不支持 | 不支持 |
| 登录认证 | 支持 | 支持 | 支持 |
| 角色认证 | 支持 | 支持 | 支持 |
| 权限认证 | 支持 | 支持 | 支持 |
| timeout 有效期 | 支持 | 支持 | 支持 |
| active-timeout 有效期 | 支持 | 支持 | 不支持 |
| id反查Token | 支持 | 支持 | 不支持 |
| 会话管理 | 支持 | 部分支持 | 不支持 |
| 注解鉴权 | 支持 | 支持 | 支持 |
| 路由拦截鉴权 | 支持 | 支持 | 支持 |
| 账号封禁 | 支持 | 支持 | 不支持 |
| 身份切换 | 支持 | 支持 | 支持 |
| 二级认证 | 支持 | 支持 | 支持 |
| 模式总结 | Token风格替换 | jwt 与 Redis 逻辑混合 | 完全舍弃Redis只用jwt |
### 6、扩展参数
你可以通过以下方式在登录时注入扩展参数:
``` java
// 登录10001账号并为生成的 Token 追加扩展参数name
StpUtil.login(10001, SaLoginConfig.setExtra("name", "zhangsan"));
// 连缀写法追加多个
StpUtil.login(10001, SaLoginConfig
.setExtra("name", "zhangsan")
.setExtra("age", 18)
.setExtra("role", "超级管理员"));
// 获取扩展参数
String name = StpUtil.getExtra("name");
// 获取任意 Token 的扩展参数
String name = StpUtil.getExtra("tokenValue", "name");
```
### 7、在多账户模式中集成 jwt
sa-token-jwt 插件默认只为 `StpUtil` 注入 `StpLogicJwtFoxXxx` 实现,自定义的 `StpUserUtil` 是不会自动注入的,我们需要帮其手动注入:
``` java
/**
* 为 StpUserUtil 注入 StpLogicJwt 实现
*/
@Autowired
public void setUserStpLogic() {
StpUserUtil.setStpLogic(new StpLogicJwtForSimple(StpUserUtil.TYPE));
}
```
### 8、自定义 SaJwtUtil 生成 token 的算法
如果需要自定义生成 token 的算法例如更换sign方式直接重写 SaJwtTemplate 对象即可:
``` java
/**
* 自定义 SaJwtUtil 生成 token 的算法
*/
@Autowired
public void setSaJwtTemplate() {
SaJwtUtil.setSaJwtTemplate(new SaJwtTemplate() {
@Override
public String generateToken(JWT jwt, String keyt) {
System.out.println("------ 自定义了 token 生成算法");
return super.generateToken(jwt, keyt);
}
});
}
```
### 9、注意点
##### 1、使用 jwt-simple 模式后is-share=false 恒等于 false。
`is-share=true` 的意思是每次登录都产生一样的 token这种策略和 [ 为每个 token 单独设定 setExtra 数据 ] 不兼容的,
为保证正确设定 Extra 数据,当使用 `jwt-simple` 模式后,`is-share` 配置项 恒等于 `false`
##### 2、使用 jwt-mixin 模式后is-concurrent 必须为 true。
`is-concurrent=false` 代表每次登录都把旧登录顶下线,但是 jwt-mixin 模式登录的 token 并不会记录在持久库数据中,
技术上来讲无法将其踢下线,所以此时顶人下线和踢人下线等 API 都属于不可用状态,所以此时 `is-concurrent` 配置项必须配置为 `true`
##### 3、使用 jwt-mixin 模式后max-try-times 恒等于 -1。
为防止框架错误判断 token 唯一性,当使用 jwt-mixin 模式后,`max-try-times` 恒等于 -1。