增加代码示例

This commit is contained in:
click33 2022-10-17 00:25:28 +08:00
parent 7142f4db36
commit 55c981ac2d
22 changed files with 470 additions and 75 deletions

View File

@ -39,13 +39,6 @@
<version>${sa-token-version}</version>
</dependency>
<!-- Sa-Token 整合 Redis (使用jdk默认序列化方式) -->
<!-- <dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis</artifactId>
<version>${sa-token-version}</version>
</dependency> -->
<!-- Sa-Token整合 Redis (使用jackson序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>

View File

@ -0,0 +1,63 @@
package com.pj.cases.up;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
/**
* Sa-Token 二级认证示例
*
* @author kong
* @since 2022-10-16
*/
@RestController
@RequestMapping("/safe/")
public class SafeAuthController {
/*
* 前提首先调用登录接口进行登录代码在 com.pj.cases.use.LoginAuthController 中有详细解释此处不再赘述
*
* 测试步骤
1前端调用 deleteProject 接口尝试删除仓库 ---- http://localhost:8081/safe/deleteProject
2后端校验会话尚未完成二级认证返回 仓库删除失败请完成二级认证后再次访问接口
3前端将信息提示给用户用户输入密码调用 openSafe 接口 ---- http://localhost:8081/safe/openSafe
4后端比对用户输入的密码完成二级认证有效期为120秒
5前端在 120 秒内再次调用 deleteProject 接口尝试删除仓库 ---- http://localhost:8081/safe/deleteProject
6后端校验会话已完成二级认证返回仓库删除成功
*/
// 删除仓库 ---- http://localhost:8081/safe/deleteProject
@RequestMapping("deleteProject")
public SaResult deleteProject(String projectId) {
// 第1步先检查当前会话是否已完成二级认证
// 这个地方既可以通过 StpUtil.isSafe() 手动判断
// 也可以通过 StpUtil.checkSafe() 或者 @SaCheckSafe 来校验校验不通过时将抛出 NotSafeException 异常
if(!StpUtil.isSafe()) {
return SaResult.error("仓库删除失败,请完成二级认证后再次访问接口");
}
// 第2步如果已完成二级认证则开始执行业务逻辑
// ...
// 第3步返回结果
return SaResult.ok("仓库删除成功");
}
// 提供密码进行二级认证 ---- http://localhost:8081/safe/openSafe
@RequestMapping("openSafe")
public SaResult openSafe(String password) {
// 比对密码此处只是举例真实项目时可拿其它参数进行校验
if("123456".equals(password)) {
// 比对成功为当前会话打开二级认证有效期为120秒
StpUtil.openSafe(120);
return SaResult.ok("二级认证成功");
}
// 如果密码校验失败则二级认证也会失败
return SaResult.error("二级认证失败");
}
}

View File

@ -1,4 +1,4 @@
package com.pj.cases;
package com.pj.cases.use;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -21,7 +21,7 @@ import cn.dev33.satoken.util.SaResult;
public class AtCheckController {
/*
* 前提1首先调用登录接口进行登录代码在 com.pj.cases.LoginAuthController 中有详细解释此处不再赘述
* 前提1首先调用登录接口进行登录代码在 com.pj.cases.use.LoginAuthController 中有详细解释此处不再赘述
* ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456
*
* 前提2项目在配置类中注册拦截器 SaInterceptor 代码在 com.pj.satoken.SaTokenConfigure

View File

@ -1,4 +1,4 @@
package com.pj.cases;
package com.pj.cases.use;
import java.util.List;
@ -19,7 +19,7 @@ import cn.dev33.satoken.util.SaResult;
public class JurAuthController {
/*
* 前提1首先调用登录接口进行登录代码在 com.pj.cases.LoginAuthController 中有详细解释此处不再赘述
* 前提1首先调用登录接口进行登录代码在 com.pj.cases.use.LoginAuthController 中有详细解释此处不再赘述
* ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456
*
* 前提2项目实现 StpInterface 接口代码在 com.pj.satoken.StpInterfaceImpl

View File

@ -1,4 +1,4 @@
package com.pj.cases;
package com.pj.cases.use;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -17,7 +17,7 @@ import cn.dev33.satoken.util.SaResult;
public class KickoutController {
/*
* 前提首先调用登录接口进行登录代码在 com.pj.cases.LoginAuthController 中有详细解释此处不再赘述
* 前提首先调用登录接口进行登录代码在 com.pj.cases.use.LoginAuthController 中有详细解释此处不再赘述
* ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456
*/

View File

@ -1,4 +1,4 @@
package com.pj.cases;
package com.pj.cases.use;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

View File

@ -0,0 +1,27 @@
package com.pj.cases.use;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.dev33.satoken.util.SaResult;
/**
* 为路由拦截鉴权准备的路示例
*
* @author kong
* @since 2022-10-15
*/
@RestController
public class RouterCheckController {
// 路由拦截鉴权测试 ---- http://localhost:8081/xxx
@RequestMapping({
"/user/doLogin", "/user/doLogin2",
"/user/info", "/admin/info", "/goods/info", "/orders/info", "/notice/info", "/comment/info",
"/router/print", "/router/print2"
})
public SaResult checkLogin() {
return SaResult.ok();
}
}

View File

@ -0,0 +1,99 @@
package com.pj.cases.use;
import java.util.Arrays;
import java.util.List;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.pj.model.SysUser;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.SaSessionCustomUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
/**
* Sa-Token Session会话示例
*
* @author kong
* @since 2022-10-15
*/
@RestController
@RequestMapping("/session/")
public class SaSessionController {
/*
* 前提首先调用登录接口进行登录代码在 com.pj.cases.use.LoginAuthController 中有详细解释此处不再赘述
*/
// 简单存取值 ---- http://localhost:8081/session/getValue
@RequestMapping("getValue")
public SaResult getValue() {
// 获取当前登录账号的专属 SaSession 对象
// 注意点1只有登录后才可以调用这个方法
// 注意点2每个账号获取到的都是不同的 SaSession 对象存取值时不会互相影响
// 注意点3SaSession HttpSession 是两个完全不同的对象不可混淆使用
SaSession session = StpUtil.getSession();
// 存值
session.set("name", "zhangsan");
session.set("age", 18);
// 取值
Object name = session.get("name");
String name2 = session.getString("name"); // 取值并转化为 String 数据类型
int age = session.getInt("age"); // int 类型
long age2 = session.getLong("age"); // long 类型
float age3 = session.getFloat("age"); // float 类型
double age4 = session.getDouble("age"); // double 类型
int age5 = session.get("age5", 22); // 取不到时就返回默认值
int age6 = session.get("age5", () -> { // 取不到时就执行 lambda 获取值
return 26;
});
/*
* 存取值范围是一次会话有效的也就是说在一次登录有效期内你可以在一个请求里存值然后在另一个请求里取值
*/
List<Object> list = Arrays.asList(name, name2, age, age2, age3, age4, age5, age6);
System.out.println(list);
return SaResult.data(list);
}
// 复杂存取值 ---- http://localhost:8081/session/getModel
@RequestMapping("getModel")
public SaResult setValue() {
// 实例化
SysUser user = new SysUser();
user.setId(10001);
user.setName("张三");
user.setAge(19);
// 写入这个对象到 SaSession
StpUtil.getSession().set("user", user);
// 然后我们就可以在任意代码处获取这个 user
SysUser user2 = StpUtil.getSession().getModel("user", SysUser.class);
// 返回
return SaResult.data(user2);
}
// 自定义Session ---- http://localhost:8081/session/customSession
@RequestMapping("customSession")
public SaResult customSession() {
// 自定义 Session 就是指使用一个特定的 key来获取 Session 对象
SaSession roleSession = SaSessionCustomUtil.getSessionById("role-1001");
// 一样可以自由的存值写值
roleSession.set("nnn", "lalala");
System.out.println(roleSession.get("nnn"));
// 返回
return SaResult.ok();
}
}

View File

@ -6,6 +6,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.exception.NotSafeException;
import cn.dev33.satoken.util.SaResult;
/**
@ -39,6 +40,13 @@ public class GlobalException {
return SaResult.error("缺少角色:" + e.getRole());
}
// 拦截二级认证校验失败异常
@ExceptionHandler(NotSafeException.class)
public SaResult handlerException(NotSafeException e) {
e.printStackTrace();
return SaResult.error("二级认证校验失败");
}
// 拦截其它所有异常
@ExceptionHandler(Exception.class)
public SaResult handlerException(Exception e) {

View File

@ -0,0 +1,84 @@
package com.pj.model;
/**
* User 实体类
*
* @author kong
* @since 2022-10-15
*/
public class SysUser {
public SysUser() {
}
public SysUser(long id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
/**
* 用户id
*/
private long id;
/**
* 用户名称
*/
private String name;
/**
* 用户年龄
*/
private int age;
/**
* @return id
*/
public long getId() {
return id;
}
/**
* @param id 要设置的 id
*/
public void setId(long id) {
this.id = id;
}
/**
* @return name
*/
public String getName() {
return name;
}
/**
* @param name 要设置的 name
*/
public void setName(String name) {
this.name = name;
}
/**
* @return age
*/
public int getAge() {
return age;
}
/**
* @param age 要设置的 age
*/
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "SysUser [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}

View File

@ -10,6 +10,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaResult;
@ -28,7 +30,36 @@ public class SaTokenConfigure implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册 Sa-Token 拦截器打开注解鉴权功能
registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");
registry.addInterceptor(new SaInterceptor(handle -> {
// 指定一条 match 规则
SaRouter
.match("/user/**") // 拦截的 path 列表可以写多个
.notMatch("/user/doLogin", "/user/doLogin2") // 排除掉的 path 列表可以写多个
.check(r -> StpUtil.checkLogin()); // 要执行的校验动作可以写完整的 lambda 表达式
// 权限校验 -- 不同模块认证不同权限
SaRouter.match("/admin/**", r -> StpUtil.checkPermission("admin"));
SaRouter.match("/goods/**", r -> StpUtil.checkPermission("goods"));
SaRouter.match("/orders/**", r -> StpUtil.checkPermission("orders"));
SaRouter.match("/notice/**", r -> StpUtil.checkPermission("notice"));
SaRouter.match("/comment/**", r -> StpUtil.checkPermission("comment"));
// 甚至你可以随意的写一个打印语句
SaRouter.match("/router/print", r -> System.out.println("----啦啦啦----"));
// 写一个完整的 lambda
SaRouter.match("/router/print2", r -> {
System.out.println("----啦啦啦2----");
// ... 其它代码
});
/*
* 相关路由都定义在 com.pj.cases.use.RouterCheckController
*/
})).addPathPatterns("/**");
}
/**

View File

@ -26,31 +26,57 @@
### 3、设置配置文件
你可以**零配置启动项目** ,但同时你也可以在 `application.yml` 中增加如下配置,定制性使用框架:
<!------------------------------ tabs:start ------------------------------>
<!------------- tab:application.yml 风格 ------------->
``` java
server:
# 端口
port: 8081
# Sa-Token配置
############## Sa-Token 配置 ##############
sa-token:
# token 名称 (同时也是cookie名称)
# token名称 (同时也是cookie名称)
token-name: satoken
# token 有效期单位s 默认30天, -1代表永不过期
# token有效期单位s 默认30天, -1代表永不过期
timeout: 2592000
# token 临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
is-share: true
# token风格
token-style: uuid
# 是否输出操作日志
is-log: false
```
如果你习惯于 `application.properties` 类型配置文件,那也很好办: <br>
百度: [springboot properties与yml 配置文件的区别](https://www.baidu.com/s?ie=UTF-8&wd=springboot%20properties%E4%B8%8Eyml%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9A%84%E5%8C%BA%E5%88%AB)
<!------------- tab:application.properties 风格 ------------->
``` java
server:
# 端口
port: 8081
############## Sa-Token 配置 ##############
# token名称 (同时也是cookie名称)
sa-token.token-name=satoken
# token有效期单位s 默认30天, -1代表永不过期
sa-token.timeout=2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
sa-token.activity-timeout=-1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
sa-token.is-concurrent=true
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
sa-token.is-share=true
# token风格
sa-token.token-style=uuid
# 是否输出操作日志
sa-token.is-log=false
```
<!---------------------------- tabs:end ------------------------------>
### 4、创建启动类

View File

@ -166,7 +166,7 @@ body{font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu
/* 调整表格的响应式 */
#main table{margin-left: 0px;}
@media screen and (min-width: 800px) {
#main table tr th{min-width: 150px;}
#main table tr th{min-width: 100px;}
}
/* 提示框加上灰色背景 */
@ -255,6 +255,8 @@ body {
padding: 8px 14px;
font-size: 14px;
transition: all 0.15s;
text-decoration: none !important;
font-weight: 400;
/* 背景 */
background-image: url(icon/dati.svg);

View File

@ -1,7 +1,7 @@
# Sa-Token 集成 Redis
---
Sa-token 默认将数据保存在内存中,此模式读写速度最快,且避免了序列化与反序列化带来的性能消耗,但是此模式也有一些缺点,比如:
Sa-Token 默认将数据保存在内存中,此模式读写速度最快,且避免了序列化与反序列化带来的性能消耗,但是此模式也有一些缺点,比如:
1. 重启后数据会丢失。
2. 无法在分布式环境中共享数据。

View File

@ -58,14 +58,14 @@ public String add() {
public SaResult deleteProject(String projectId) {
// 第1步先检查当前会话是否已完成二级认证
if(!StpUtil.isSafe()) {
return SaResult.error("请完成二级认证后再次访问接口");
return SaResult.error("仓库删除失败,请完成二级认证后再次访问接口");
}
// 第2步如果已完成二级认证则开始执行业务逻辑
// ...
// 第3步返回结果
return SaResult.ok();
return SaResult.ok("仓库删除成功");
}
// 提供密码进行二级认证
@ -86,9 +86,16 @@ public SaResult openSafe(String password) {
调用步骤:
1. 前端调用 `deleteProject` 接口,尝试删除仓库。
2. 后端校验会话尚未完成二级认证,返回: `请完成二级认证后再次访问接口`。
2. 后端校验会话尚未完成二级认证,返回: `仓库删除失败,请完成二级认证后再次访问接口`。
3. 前端将信息提示给用户,用户输入密码,调用 `openSafe` 接口。
4. 后端比对用户输入的密码完成二级认证有效期为120秒。
5. 前端在 120 秒内再次调用 `deleteProject` 接口,尝试删除仓库。
6. 后端校验会话已完成二级认证,仓库删除成功。
6. 后端校验会话已完成二级认证,返回:`仓库删除成功`
---
<a class="case-btn" href="https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/up/SafeAuthController.java"
target="_blank">
本章代码示例Sa-Token 二级认证 —— [ com.pj.cases.up.SafeAuthController.java ]
</a>

View File

@ -1,11 +1,7 @@
# 注解鉴权
<a class="case-btn" href="https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/AtCheckController.java"
target="_blank">
本章代码示例Sa-Token 注解鉴权 —— [ com.pj.cases.AtCheckController.java ]
</a>
---
### 注解鉴权
有同学表示:尽管使用代码鉴权非常方便,但是我仍希望把鉴权逻辑和业务逻辑分离开来,我可以使用注解鉴权吗?当然可以!<br>
@ -162,6 +158,11 @@ public class TestController {
---
<a class="case-btn" href="https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/use/AtCheckController.java"
target="_blank">
本章代码示例Sa-Token 注解鉴权 —— [ com.pj.cases.use.AtCheckController.java ]
</a>
<a class="dt-btn" href="https://www.wenjuan.ltd/s/ARJvIbA/" target="_blank">本章小练习Sa-Token 基础 - 注解鉴权,章节测试</a>

View File

@ -1,15 +1,17 @@
# 框架配置
你可以**零配置启动框架** <br>
但同时你也可以通过配置,定制性使用框架,`Sa-Token`支持多种方式配置框架信息
你可以**零配置启动框架**,但同时你也可以通过一定的参数配置,定制性使用框架,`Sa-Token`支持多种方式配置框架信息
---
### 方式1、在 application.yml 配置
<!------------------------------ tabs:start ------------------------------>
<!------------- tab:application.yml 风格 ------------->
``` java
# Sa-Token 配置
############## Sa-Token 配置 ##############
############## 在线参考https://sa-token.dev33.cn/doc.html#/use/config ##############
sa-token:
# token名称 (同时也是cookie名称)
token-name: satoken
@ -27,19 +29,42 @@ sa-token:
is-log: false
```
如果你习惯于 `application.properties` 类型的配置文件,那也很好办: 百度: [springboot properties与yml 配置文件的区别](https://www.baidu.com/s?ie=UTF-8&wd=springboot%20properties%E4%B8%8Eyml%20%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E7%9A%84%E5%8C%BA%E5%88%AB)
<!------------- tab:application.properties 风格 ------------->
``` java
############## Sa-Token 配置 ##############
############## 在线参考https://sa-token.dev33.cn/doc.html#/use/config ##############
# token名称 (同时也是cookie名称)
sa-token.token-name=satoken
# token有效期单位s 默认30天, -1代表永不过期
sa-token.timeout=2592000
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
sa-token.activity-timeout=-1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
sa-token.is-concurrent=true
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
sa-token.is-share=true
# token风格
sa-token.token-style=uuid
# 是否输出操作日志
sa-token.is-log=false
```
<!---------------------------- tabs:end ------------------------------>
### 方式2、通过代码配置
模式1
<!------------------------------ tabs:start ------------------------------>
<!------------- tab:模式 1 ------------->
``` java
/**
* Sa-Token代码方式进行配置
*/
@Configuration
public class SaTokenConfigure {
// 获取配置Bean (以代码的方式配置Sa-Token, 此配置会覆盖yml中的配置)
// 获取配置Bean (以代码的方式配置Sa-Token, 此配置会覆盖 application.yml 中的配置)
@Bean
@Primary
public SaTokenConfig getSaTokenConfigPrimary() {
@ -53,21 +78,36 @@ public class SaTokenConfigure {
config.setIsLog(false); // 是否输出操作日志
return config;
}
}
```
模式2
<!------------- tab:模式 2 ------------->
``` java
// 以代码的方式配置Sa-Token-Config
@Autowired
public void configSaToken(SaTokenConfig config) {
// config.setTokenName("satoken333"); // token名称 (同时也是cookie名称)
// ...
/**
* Sa-Token代码方式进行配置
*/
@Configuration
public class SaTokenConfigure {
// 以代码的方式配置 SaTokenConfig
// 此配置会与 application.yml 中的配置合并 (代码配置优先)
@Autowired
public void configSaToken(SaTokenConfig config) {
SaTokenConfig config = new SaTokenConfig();
config.setTokenName("satoken"); // token名称 (同时也是cookie名称)
config.setTimeout(30 * 24 * 60 * 60); // token有效期单位s 默认30天
config.setActivityTimeout(-1); // token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
config.setIsConcurrent(true); // 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
config.setIsShare(true); // 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
config.setTokenStyle("uuid"); // token风格
config.setIsLog(false); // 是否输出操作日志
return config;
}
}
```
<!---------------------------- tabs:end ------------------------------>
PS两者的区别在于**`模式1会覆盖yml中的配置模式2会与yml中的配置合并`**
两者的区别在于:
- 模式 1 会覆盖 application.yml 中的配置。
- 模式 2 会与 application.yml 中的配置合并(代码配置优先)。
---

View File

@ -1,10 +1,5 @@
# 权限认证
<a class="case-btn" href="https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/JurAuthController.java"
target="_blank">
本章代码示例Sa-Token 权限认证 —— [ com.pj.cases.JurAuthController.java ]
</a>
---
@ -196,4 +191,9 @@ StpUtil.hasPermission("index.html"); // false
---
<a class="case-btn" href="https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/use/JurAuthController.java"
target="_blank">
本章代码示例Sa-Token 权限认证 —— [ com.pj.cases.use.JurAuthController.java ]
</a>
<a class="dt-btn" href="https://www.wenjuan.ltd/s/ZfIjYr9/" target="_blank">本章小练习Sa-Token 基础 - 权限认证,章节测试</a>

View File

@ -1,14 +1,5 @@
# 踢人下线
<a class="case-btn" href="https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/KickoutController.java"
target="_blank">
本章代码示例Sa-Token 踢人下线 —— [ com.pj.cases.KickoutController.java ]
</a>
---
### 设计思路
所谓踢人下线,核心操作就是找到指定 `loginId` 对应的 `Token`,并设置其失效。
![踢下线](https://oss.dev33.cn/sa-token/doc/kickout.png)
@ -40,6 +31,11 @@ StpUtil.kickoutByTokenValue("token"); // 将指定 Token 踢下线
---
<a class="case-btn" href="https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/use/KickoutController.java"
target="_blank">
本章代码示例Sa-Token 踢人下线 —— [ com.pj.cases.use.KickoutController.java ]
</a>
<a class="dt-btn" href="https://www.wenjuan.ltd/s/MFNN7bK/" target="_blank">本章小练习Sa-Token 基础 - 踢人下线,章节测试</a>

View File

@ -1,10 +1,5 @@
# 登录认证
<a class="case-btn" href="https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/LoginAuthController.java"
target="_blank">
本章代码示例Sa-Token 登录认证 —— [ com.pj.cases.LoginAuthController.java ]
</a>
---
@ -175,5 +170,10 @@ public class LoginController {
---
<a class="case-btn" href="https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/use/LoginAuthController.java"
target="_blank">
本章代码示例Sa-Token 登录认证 —— [ com.pj.cases.use.LoginAuthController.java ]
</a>
<a class="dt-btn" href="https://www.wenjuan.ltd/s/UZBZJvb2ej/" target="_blank">本章小练习Sa-Token 基础 - 登录认证,章节测试</a>

View File

@ -1,4 +1,5 @@
# 路由拦截鉴权
---
假设我们有如下需求:
@ -41,6 +42,12 @@ public class SaTokenConfigure implements WebMvcConfigurer {
public void addInterceptors(InterceptorRegistry registry) {
// 注册 Sa-Token 拦截器,定义详细认证规则
registry.addInterceptor(new SaInterceptor(handler -> {
// 指定一条 match 规则
SaRouter
.match("/**") // 拦截的 path 列表,可以写多个
.notMatch("/user/doLogin") // 排除掉的 path 列表,可以写多个
.check(r -> StpUtil.checkLogin()); // 要执行的校验动作,可以写完整的 lambda 表达式
// 根据路由划分模块,不同模块不同鉴权
SaRouter.match("/user/**", r -> StpUtil.checkPermission("user"));
SaRouter.match("/admin/**", r -> StpUtil.checkPermission("admin"));
@ -68,13 +75,13 @@ public class SaTokenConfigure implements WebMvcConfigurer {
// 注册路由拦截器,自定义认证规则
registry.addInterceptor(new SaInterceptor(handler -> {
// 登录认证 -- 拦截所有路由,并排除/user/doLogin 用于开放登录
// 登录校验 -- 拦截所有路由,并排除/user/doLogin 用于开放登录
SaRouter.match("/**", "/user/doLogin", r -> StpUtil.checkLogin());
// 角色认证 -- 拦截以 admin 开头的路由,必须具备 admin 角色或者 super-admin 角色才可以通过认证
// 角色校验 -- 拦截以 admin 开头的路由,必须具备 admin 角色或者 super-admin 角色才可以通过认证
SaRouter.match("/admin/**", r -> StpUtil.checkRoleOr("admin", "super-admin"));
// 权限认证 -- 不同模块认证不同权限
// 权限校验 -- 不同模块校验不同权限
SaRouter.match("/user/**", r -> StpUtil.checkPermission("user"));
SaRouter.match("/admin/**", r -> StpUtil.checkPermission("admin"));
SaRouter.match("/goods/**", r -> StpUtil.checkPermission("goods"));
@ -227,6 +234,11 @@ public void addInterceptors(InterceptorRegistry registry) {
```
---
<a class="case-btn" href="https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/SaTokenConfigure.java"
target="_blank">
本章代码示例Sa-Token 路由拦截鉴权 —— [ com.pj.satoken.SaTokenConfigure.java ]
</a>
<a class="dt-btn" href="https://www.wenjuan.ltd/s/rY7VFv/" target="_blank">本章小练习Sa-Token 基础 - 路由拦截鉴权,章节测试</a>

View File

@ -1,4 +1,5 @@
# Session会话
---
### Session是什么
@ -169,5 +170,10 @@ StpUtil.getAnonTokenSession();
---
<a class="case-btn" href="https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/SaSessionController.java"
target="_blank">
本章代码示例Sa-Token Session 会话 —— [ com.pj.cases.use.SaSessionController.java ]
</a>
<a class="dt-btn" href="https://www.wenjuan.ltd/s/MNnUr2V/" target="_blank">本章小练习Sa-Token 基础 - Session 会话,章节测试</a>