mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-04-05 17:37:53 +08:00
完善新版本特性文档
This commit is contained in:
parent
d491f4083f
commit
3bec16627e
@ -56,8 +56,8 @@ public String insert(SysUser user) {
|
||||
|
||||
将某个账号踢下线(待到对方再次访问系统时会抛出`NotLoginException`异常)
|
||||
``` java
|
||||
// 使账号id为 10001 的会话强制注销登录
|
||||
StpUtil.logoutByLoginId(10001);
|
||||
// 将账号id为 10001 的会话踢下线
|
||||
StpUtil.kickout(10001);
|
||||
```
|
||||
|
||||
在 Sa-Token 中,绝大多数功能都可以 **一行代码** 完成:
|
||||
@ -66,14 +66,14 @@ StpUtil.login(10001); // 标记当前会话登录的账号id
|
||||
StpUtil.getLoginId(); // 获取当前会话登录的账号id
|
||||
StpUtil.isLogin(); // 获取当前会话是否已经登录, 返回true或false
|
||||
StpUtil.logout(); // 当前会话注销登录
|
||||
StpUtil.logoutByLoginId(10001); // 让账号为10001的会话注销登录(踢人下线)
|
||||
StpUtil.kickout(10001); // 将账号为10001的会话踢下线
|
||||
StpUtil.hasRole("super-admin"); // 查询当前账号是否含有指定角色标识, 返回true或false
|
||||
StpUtil.hasPermission("user:add"); // 查询当前账号是否含有指定权限, 返回true或false
|
||||
StpUtil.getSession(); // 获取当前账号id的Session
|
||||
StpUtil.getSessionByLoginId(10001); // 获取账号id为10001的Session
|
||||
StpUtil.getTokenValueByLoginId(10001); // 获取账号id为10001的token令牌值
|
||||
StpUtil.login(10001, "PC"); // 指定设备标识登录,常用于“同端互斥登录”
|
||||
StpUtil.logoutByLoginId(10001, "PC"); // 指定设备标识进行强制注销 (不同端不受影响)
|
||||
StpUtil.kickout(10001, "PC"); // 指定账号指定设备标识踢下线 (不同端不受影响)
|
||||
StpUtil.openSafe(120); // 在当前会话开启二级认证,有效期为120秒
|
||||
StpUtil.checkSafe(); // 校验当前会话是否处于二级认证有效期内,校验失败会抛出异常
|
||||
StpUtil.switchTo(10044); // 将当前会话身份临时切换为其它账号
|
||||
|
@ -111,7 +111,7 @@ public class SaManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 容器操作 Bean
|
||||
* 上下文 Bean
|
||||
*/
|
||||
private volatile static SaTokenContext saTokenContext;
|
||||
public static void setSaTokenContext(SaTokenContext saTokenContext) {
|
||||
|
@ -42,8 +42,8 @@ public @interface SaCheckPermission {
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 例2: orRole={"admin", "manager", "staff"},具有三个角色其一即可 <br>
|
||||
* 例3: orRole={"admin, manager, staff"},必须三个角色同时具备
|
||||
* 例2: orRole = {"admin", "manager", "staff"},具有三个角色其一即可 <br>
|
||||
* 例3: orRole = {"admin, manager, staff"},必须三个角色同时具备
|
||||
* </p>
|
||||
*/
|
||||
String[] orRole() default {};
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.pj.satoken;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
@ -10,7 +9,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import com.pj.util.AjaxJson;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.filter.SaServletFilter;
|
||||
import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
|
||||
@ -77,12 +75,12 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
||||
/**
|
||||
* 重写 Sa-Token 框架内部算法策略
|
||||
*/
|
||||
@PostConstruct
|
||||
@Autowired
|
||||
public void rewriteSaStrategy() {
|
||||
// 重写Sa-Token的注解处理器,增加注解合并功能
|
||||
SaStrategy.me.setGetAnnotation((element, annotationClass) -> {
|
||||
return AnnotatedElementUtils.getMergedAnnotation(element, SaCheckLogin.class);
|
||||
});
|
||||
SaStrategy.me.getAnnotation = (element, annotationClass) -> {
|
||||
return AnnotatedElementUtils.getMergedAnnotation(element, annotationClass);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
</p>
|
||||
|
||||
<p>登录之后才能显示:<span sa:login>value</span></p>
|
||||
<p>不登录之后才能显示:<span sa:notLogin>value</span></p>
|
||||
<p>不登录才能显示:<span sa:notLogin>value</span></p>
|
||||
|
||||
<p>具有角色 admin 才能显示:<span sa:hasRole="admin">value</span></p>
|
||||
<p>同时具备多个角色才能显示:<span sa:hasRoleAnd="admin, ceo, cto">value</span></p>
|
||||
@ -28,7 +28,7 @@
|
||||
|
||||
<p th:if="${stp.isLogin()}">
|
||||
从SaSession中取值:
|
||||
<span th:text="${stp.getSession().get('name', )}"></span>
|
||||
<span th:text="${stp.getSession().get('name', '')}"></span>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
@ -58,8 +58,8 @@ public String insert(SysUser user) {
|
||||
|
||||
将某个账号踢下线(待到对方再次访问系统时会抛出`NotLoginException`异常)
|
||||
``` java
|
||||
// 使账号id为 10001 的会话强制注销登录
|
||||
StpUtil.logoutByLoginId(10001);
|
||||
// 将账号id为 10001 的会话踢下线
|
||||
StpUtil.kickout(10001);
|
||||
```
|
||||
|
||||
在 Sa-Token 中,绝大多数功能都可以 **一行代码** 完成:
|
||||
@ -68,14 +68,14 @@ StpUtil.login(10001); // 标记当前会话登录的账号id
|
||||
StpUtil.getLoginId(); // 获取当前会话登录的账号id
|
||||
StpUtil.isLogin(); // 获取当前会话是否已经登录, 返回true或false
|
||||
StpUtil.logout(); // 当前会话注销登录
|
||||
StpUtil.logoutByLoginId(10001); // 让账号为10001的会话注销登录(踢人下线)
|
||||
StpUtil.kickout(10001); // 将账号为10001的会话踢下线
|
||||
StpUtil.hasRole("super-admin"); // 查询当前账号是否含有指定角色标识, 返回true或false
|
||||
StpUtil.hasPermission("user:add"); // 查询当前账号是否含有指定权限, 返回true或false
|
||||
StpUtil.getSession(); // 获取当前账号id的Session
|
||||
StpUtil.getSessionByLoginId(10001); // 获取账号id为10001的Session
|
||||
StpUtil.getTokenValueByLoginId(10001); // 获取账号id为10001的token令牌值
|
||||
StpUtil.login(10001, "PC"); // 指定设备标识登录,常用于“同端互斥登录”
|
||||
StpUtil.logoutByLoginId(10001, "PC"); // 指定设备标识进行强制注销 (不同端不受影响)
|
||||
StpUtil.kickout(10001, "PC"); // 指定账号指定设备标识踢下线 (不同端不受影响)
|
||||
StpUtil.openSafe(120); // 在当前会话开启二级认证,有效期为120秒
|
||||
StpUtil.checkSafe(); // 校验当前会话是否处于二级认证有效期内,校验失败会抛出异常
|
||||
StpUtil.switchTo(10044); // 将当前会话身份临时切换为其它账号
|
||||
|
@ -29,7 +29,7 @@
|
||||
- [会话治理](/up/search-session)
|
||||
- [全局侦听器](/up/global-listener)
|
||||
- [全局过滤器](/up/global-filter)
|
||||
- [多账号验证](/up/many-account)
|
||||
- [多账号认证](/up/many-account)
|
||||
<!-- - [微服务](/senior/dcs) -->
|
||||
|
||||
- **单点登录**
|
||||
@ -63,6 +63,7 @@
|
||||
- [Quick-Login快速登录插件](/plugin/quick-login)
|
||||
- [Alone独立Redis插件](/plugin/alone-redis)
|
||||
- [持久层扩展](/plugin/dao-extend)
|
||||
- [和 Thymeleaf 集成](/plugin/thymeleaf-extend)
|
||||
|
||||
- **其它**
|
||||
- [更新日志](/more/update-log)
|
||||
|
@ -61,6 +61,14 @@ body{font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu
|
||||
.lang-xml .token.tag *{color: #db2d20;}
|
||||
.lang-xml .token.attr-value{color: #A6E22E;}
|
||||
|
||||
/* html语言样式优化 */
|
||||
.lang-html .token.comment{color: #CDAB53;}
|
||||
.lang-html .token.tag *{color: #db2d20;}
|
||||
.lang-html .token.tag .attr-name,
|
||||
.lang-html .token.tag .attr-name *{color: #A6E22E; opacity: 0.9;}
|
||||
.lang-html .token.tag .attr-value,
|
||||
.lang-html .token.tag .attr-value *{color: #E6DB74; opacity: 0.9;}
|
||||
|
||||
/* java语言样式优化 */
|
||||
.main-box .lang-java{color: #01a252 !important;; opacity: 1;}
|
||||
.lang-java .token.keyword{color: #db2d20;}
|
||||
|
@ -12,6 +12,7 @@ SaManager.getStpInterface(); // 获取权限认证对象
|
||||
SaManager.getSaTokenAction(); // 获取框架行为对象
|
||||
SaManager.getSaTokenContext(); // 获取上下文处理对象
|
||||
SaManager.getSaTokenListener(); // 获取侦听器对象
|
||||
SaManager.getSaTemp(); // 获取临时令牌验证模块对象
|
||||
SaManager.getStpLogic("type"); // 获取指定账号类型的StpLogic对象
|
||||
```
|
||||
|
||||
|
125
sa-token-doc/doc/plugin/thymeleaf-extend.md
Normal file
125
sa-token-doc/doc/plugin/thymeleaf-extend.md
Normal file
@ -0,0 +1,125 @@
|
||||
# Thymeleaf 标签方言
|
||||
|
||||
本插件的作用是让我们可以在 Thymeleaf 页面中使用 Sa-Token 相关API,俗称 —— 标签方言。
|
||||
|
||||
---
|
||||
|
||||
### 1、引入依赖
|
||||
首先我们确保项目已经引入 Thymeleaf 依赖,然后在此基础上继续添加:
|
||||
|
||||
``` xml
|
||||
<!-- 在 thymeleaf 标签中使用 Sa-Token -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-dialect-thymeleaf</artifactId>
|
||||
<version>${sa.top.version}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
||||
### 2、注册标签方言对象
|
||||
在 SaTokenConfigure 配置类中注册 Bean
|
||||
``` java
|
||||
@Configuration
|
||||
public class SaTokenConfigure {
|
||||
// Sa-Token 标签方言 (Thymeleaf版)
|
||||
@Bean
|
||||
public SaTokenDialect getSaTokenDialect() {
|
||||
return new SaTokenDialect();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### 3、使用标签方言
|
||||
然后我们就可以愉快的使用在 Thymeleaf 页面中使用标签方言了
|
||||
|
||||
##### 3.1、登录判断
|
||||
``` html
|
||||
<h2>标签方言测试页面</h2>
|
||||
<p>
|
||||
登录之后才能显示:
|
||||
<span sa:login>value</span>
|
||||
</p>
|
||||
<p>
|
||||
不登录才能显示:
|
||||
<span sa:notLogin>value</span>
|
||||
</p>
|
||||
```
|
||||
|
||||
##### 3.2、角色判断
|
||||
``` html
|
||||
<p>
|
||||
具有角色 admin 才能显示:
|
||||
<span sa:hasRole="admin">value</span>
|
||||
</p>
|
||||
<p>
|
||||
同时具备多个角色才能显示:
|
||||
<span sa:hasRoleAnd="admin, ceo, cto">value</span>
|
||||
</p>
|
||||
<p>
|
||||
只要具有其中一个角色就能显示:
|
||||
<span sa:hasRoleOr="admin, ceo, cto">value</span>
|
||||
</p>
|
||||
<p>
|
||||
不具有角色 admin 才能显示:
|
||||
<span sa:lackRole="admin">value</span>
|
||||
</p>
|
||||
```
|
||||
|
||||
##### 3.3、权限判断
|
||||
``` html
|
||||
<p>
|
||||
具有权限 user-add 才能显示:
|
||||
<span sa:hasPermission="user-add">value</span>
|
||||
</p>
|
||||
<p>
|
||||
同时具备多个权限才能显示:
|
||||
<span sa:hasPermissionAnd="user-add, user-delete, user-get">value</span>
|
||||
</p>
|
||||
<p>
|
||||
只要具有其中一个权限就能显示:
|
||||
<span sa:hasPermissionOr="user-add, user-delete, user-get">value</span>
|
||||
</p>
|
||||
<p>
|
||||
不具有权限 user-add 才能显示:
|
||||
<span sa:lackPermission="user-add">value</span>
|
||||
</p>
|
||||
```
|
||||
|
||||
|
||||
### 4、调用 Sa-Token 相关API
|
||||
|
||||
以上的标签方言,可以满足我们大多数场景下的权限判断,然后有时候我们依然需要更加灵活的在页面中调用 Sa-Token 框架API
|
||||
|
||||
首先在 SaTokenConfigure 配置类中为 Thymeleaf 配置全局对象:
|
||||
|
||||
``` java
|
||||
public class SaTokenConfigure{
|
||||
// ... 其它代码
|
||||
|
||||
// 为 Thymeleaf 注入全局变量,以便在页面中调用 Sa-Token 的方法
|
||||
@Autowired
|
||||
private void configureThymeleafStaticVars(ThymeleafViewResolver viewResolver) {
|
||||
viewResolver.addStaticVariable("stp", StpUtil.stpLogic);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
然后我们就可以在页面上调用 StpLogic 的 API 了,例如:
|
||||
|
||||
``` html
|
||||
<p>调用 StpLogic 方法调用测试</p>
|
||||
<p th:if="${stp.isLogin()}">
|
||||
从SaSession中取值:
|
||||
<span th:text="${stp.getSession().get('name')}"></span>
|
||||
</p>
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -181,16 +181,16 @@ public class SaSsoServerApplication {
|
||||
|
||||

|
||||
|
||||
可以看到这个页面非常简陋,这是因为我们以上的代码示例,主要目标是为了带大家从零搭建一个可用的SSO认证服务端,所以就对一些不太必要的步骤做了简化
|
||||
可以看到这个页面目前非常简陋,这是因为我们以上的代码示例,主要目标是为了带大家从零搭建一个可用的SSO认证服务端,所以就对一些不太必要的步骤做了简化。
|
||||
|
||||
大家可以下载运行一下官方仓库里的示例`/sa-token-demo/sa-token-demo-sso-server/`,里面有制作好的登录页面:
|
||||
|
||||

|
||||
|
||||
默认账号密码为:`sa / 123456`,大家先别着急点击登录,因为我们还没有搭建对应的 Client 端项目,
|
||||
默认账号密码为:`sa / 123456`,先别着急点击登录,因为我们还没有搭建对应的 Client 端项目,
|
||||
真实项目中我们是不会直接从浏览器访问 `/sso/auth` 授权地址的,我们需要在 Client 端点击登录按钮重定向而来。
|
||||
|
||||
现在我们先来看看除了 `/sso/auth` 统一授权地址,这个 SSO-Server 认证中心还开放了哪些API呢,且往下看
|
||||
现在我们先来看看除了 `/sso/auth` 统一授权地址,这个 SSO-Server 认证中心还开放了哪些API。
|
||||
|
||||
### 5、API 列表
|
||||
|
||||
@ -244,7 +244,7 @@ http://{host}:{port}/sso/checkTicket
|
||||
| 参数 | 是否必填 | 说明 |
|
||||
| :-------- | :-------- | :-------- |
|
||||
| ticket | 是 | 在步骤 5.1 中授权重定向时的 ticket 参数 |
|
||||
| ssoLogoutCall | 否 | 单点注销时的回调通知地址,只在SSO模式三时需要携带此参数|
|
||||
| ssoLogoutCall | 否 | 单点注销时的回调通知地址,只在SSO模式三单点注销时需要携带此参数|
|
||||
|
||||
返回值场景:
|
||||
- 返回空,代表校验失败。
|
||||
@ -267,7 +267,7 @@ http://{host}:{port}/sso/logout
|
||||
|
||||
此接口有两种调用方式
|
||||
|
||||
##### 方式一:在前端页面引导用户直接跳转,并带有 back 参数
|
||||
##### 方式一:在 Client 的前端页面引导用户直接跳转,并带有 back 参数
|
||||
例如:`http://{host}:{port}/sso/logout?back=xxx`,代表用户注销成功后返回back地址
|
||||
|
||||
##### 方式二:在 Client 的后端通过 http 工具来调用
|
||||
|
@ -40,17 +40,19 @@ OK,所有理论就绪,下面开始实战:
|
||||
``` yml
|
||||
sa-token:
|
||||
cookie:
|
||||
# 配置Cookie作用域 (这个配置原本是被注释掉的,现在我们将其打开)
|
||||
# 配置Cookie作用域
|
||||
domain: stp.com
|
||||
```
|
||||
|
||||
注:在SSO模式一测试完毕之后,一定要将这个配置再次注释掉,因为模式一与模式二三使用不同的授权流程,这行配置会影响到我们模式二和模式三的正常运行。
|
||||
这个配置原本是被注释掉的,现在将其打开。另外我们格外需要注意:
|
||||
在SSO模式一测试完毕之后,一定要将这个配置再次注释掉,因为模式一与模式二三使用不同的授权流程,这行配置会影响到我们模式二和模式三的正常运行。
|
||||
|
||||
|
||||
|
||||
|
||||
### 4、搭建 Client 端项目
|
||||
|
||||
> 整合示例在官方仓库的 `/sa-token-demo/sa-token-demo-sso1-client/`,如遇到难点可结合源码进行测试学习。
|
||||
> 搭建示例在官方仓库的 `/sa-token-demo/sa-token-demo-sso1-client/`,如遇到难点可结合源码进行测试学习。
|
||||
|
||||
|
||||
#### 4.1、引入依赖
|
||||
|
@ -122,7 +122,7 @@ public Object myinfo() {
|
||||
5. Server 端注销下线。
|
||||
6. 单点注销完成。
|
||||
|
||||
这些逻辑 Sa-Token 内部已经封装完毕,你只需按照文章增加以下配置即可:
|
||||
这些逻辑 Sa-Token 内部已经封装完毕,你只需按照文档增加以下配置即可:
|
||||
|
||||
#### 4.1、SSO-Client 端新增配置
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
### 自定义侦听器实现
|
||||
|
||||
新建`MySaTokenListener.java`,继承`SaTokenListener`接口,并添加上注解`@Component`,保证此类被`SpringBoot`扫描到
|
||||
|
||||
``` java
|
||||
/**
|
||||
* 自定义侦听器的实现
|
||||
@ -33,13 +34,13 @@ public class MySaTokenListener implements SaTokenListener {
|
||||
|
||||
/** 每次被踢下线时触发 */
|
||||
@Override
|
||||
public void doLogoutByLoginId(String loginType, Object loginId, String tokenValue, String device) {
|
||||
public void doKickout(String loginType, Object loginId, String tokenValue) {
|
||||
// ...
|
||||
}
|
||||
|
||||
/** 每次被顶下线时触发 */
|
||||
@Override
|
||||
public void doReplaced(String loginType, Object loginId, String tokenValue, String device) {
|
||||
public void doReplaced(String loginType, Object loginId, String tokenValue) {
|
||||
// ...
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 多账号验证
|
||||
# 多账号认证
|
||||
---
|
||||
|
||||
### 0、需求场景
|
||||
@ -80,48 +80,20 @@ public String info() {
|
||||
|
||||
我们期待一种`[注解继承/合并]`的能力,即:自定义一个注解,标注上`@SaCheckLogin(type = "user")`,然后在方法上标注这个自定义注解,效果等同于标注`@SaCheckLogin(type = "user")`
|
||||
|
||||
很遗憾,JDK默认的注解处理器并没有提供这种`[注解继承/合并]`的能力,不过好在我们可以利用Spring的注解处理器,达到同样的目的
|
||||
很遗憾,JDK默认的注解处理器并没有提供这种`[注解继承/合并]`的能力,不过好在我们可以利用 Spring 的注解处理器,达到同样的目的
|
||||
|
||||
1. 重写Sa-Token默认的注解处理器
|
||||
|
||||
``` java
|
||||
/**
|
||||
* 继承Sa-Token行为Bean默认实现, 重写部分逻辑
|
||||
*/
|
||||
@Component
|
||||
public class MySaTokenAction extends SaTokenActionDefaultImpl {
|
||||
|
||||
/**
|
||||
* 重写Sa-Token的注解处理器,加强注解合并功能
|
||||
*/
|
||||
@Override
|
||||
protected void validateAnnotation(AnnotatedElement target) {
|
||||
|
||||
// 校验 @SaCheckLogin 注解
|
||||
if(AnnotatedElementUtils.isAnnotated(target, SaCheckLogin.class)) {
|
||||
SaCheckLogin at = AnnotatedElementUtils.getMergedAnnotation(target, SaCheckLogin.class);
|
||||
SaManager.getStpLogic(at.type()).checkByAnnotation(at);
|
||||
}
|
||||
|
||||
// 校验 @SaCheckRole 注解
|
||||
if(AnnotatedElementUtils.isAnnotated(target, SaCheckRole.class)) {
|
||||
SaCheckRole at = AnnotatedElementUtils.getMergedAnnotation(target, SaCheckRole.class);
|
||||
SaManager.getStpLogic(at.type()).checkByAnnotation(at);
|
||||
}
|
||||
|
||||
// 校验 @SaCheckPermission 注解
|
||||
if(AnnotatedElementUtils.isAnnotated(target, SaCheckPermission.class)) {
|
||||
SaCheckPermission at = AnnotatedElementUtils.getMergedAnnotation(target, SaCheckPermission.class);
|
||||
SaManager.getStpLogic(at.type()).checkByAnnotation(at);
|
||||
}
|
||||
|
||||
// 校验 @SaCheckSafe 注解
|
||||
if(AnnotatedElementUtils.isAnnotated(target, SaCheckSafe.class)) {
|
||||
SaCheckSafe at = AnnotatedElementUtils.getMergedAnnotation(target, SaCheckSafe.class);
|
||||
SaManager.getStpLogic(null).checkByAnnotation(at);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public class SaTokenConfigure {
|
||||
@Autowired
|
||||
public void rewriteSaStrategy() {
|
||||
// 重写Sa-Token的注解处理器,增加注解合并功能
|
||||
SaStrategy.me.getAnnotation = (element, annotationClass) -> {
|
||||
return AnnotatedElementUtils.getMergedAnnotation(element, annotationClass);
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -184,6 +156,3 @@ public class StpUserUtil {
|
||||
|
||||
再次调用 `StpUserUtil.login(10001)` 进行登录授权时,token的名称将不再是 `satoken`,而是我们重写后的 `satoken-user`
|
||||
|
||||
|
||||
|
||||
> 不同体系账号在登录时设置不同的token有效期等信息,详见[登录时指定token有效期](/up/remember-me?id=登录时指定token有效期)
|
@ -14,8 +14,8 @@ Sa-Token在api设计时充分考虑了这一点,暴露出多个api进行此类
|
||||
// 获取指定账号10001的`tokenValue`值
|
||||
StpUtil.getTokenValueByLoginId(10001);
|
||||
|
||||
// 将账号10001的会话注销登录(踢人下线)
|
||||
StpUtil.logoutByLoginId(10001);
|
||||
// 将账号10001的会话注销登录
|
||||
StpUtil.logout(10001);
|
||||
|
||||
// 获取账号10001的Session对象, 如果session尚未创建, 则新建并返回
|
||||
StpUtil.getSessionByLoginId(10001);
|
||||
|
@ -21,10 +21,10 @@ StpUtil.login(10001, "PC");
|
||||
|
||||
#### 指定设备标识强制注销
|
||||
``` java
|
||||
// 指定`账号id`和`设备标识`进行强制注销 (踢人下线)
|
||||
StpUtil.logoutByLoginId(10001, "PC");
|
||||
// 指定`账号id`和`设备标识`进行强制注销
|
||||
StpUtil.logout(10001, "PC");
|
||||
```
|
||||
如果第二个参数填写null或不填,代表将这个账号id所有在线端踢下线,被踢出者再次访问系统时会抛出 `NotLoginException` 异常,场景值=`-5`
|
||||
如果第二个参数填写null或不填,代表将这个账号id所有在线端强制注销,被踢出者再次访问系统时会抛出 `NotLoginException` 异常,场景值=`-2`
|
||||
|
||||
|
||||
#### 查询当前登录的设备标识
|
||||
@ -40,5 +40,3 @@ StpUtil.getLoginDevice();
|
||||
StpUtil.getTokenValueByLoginId(10001, "APP");
|
||||
```
|
||||
|
||||
|
||||
> 不同设备账号在登录时设置不同的token有效期等信息, 详见[登录时指定token有效期](/up/remember-me?id=登录时指定token有效期)
|
@ -37,27 +37,24 @@ Sa-Token默认的token生成策略是uuid风格,其模样类似于:`623368f0
|
||||
|
||||
如果你觉着以上风格都不是你喜欢的类型,那么你还可以**自定义token生成策略**,来定制化token生成风格 <br>
|
||||
|
||||
怎么做呢?只需要重写`SaTokenAction`接口的`createToken`方法即可
|
||||
怎么做呢?只需要重写 `SaStrategy` 策略类的 `createToken` 算法即可
|
||||
|
||||
|
||||
#### 参考步骤如下:
|
||||
1、新建文件`MySaTokenAction.java`,继承`SaTokenActionDefaultImpl`默认实现类, 并添加上注解`@Component`,保证此类被`springboot`扫描到
|
||||
1、在`SaTokenConfigure`配置类中添加代码:
|
||||
``` java
|
||||
package com.pj.satoken;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import cn.dev33.satoken.action.SaTokenActionDefaultImpl;
|
||||
|
||||
/**
|
||||
* 继承Sa-Token行为Bean默认实现, 重写部分逻辑
|
||||
*/
|
||||
@Component
|
||||
public class MySaTokenAction extends SaTokenActionDefaultImpl {
|
||||
// 重写token生成策略
|
||||
@Override
|
||||
public String createToken(Object loginId, String loginType) {
|
||||
return SaFoxUtil.getRandomString(60); // 随机60位字符串
|
||||
}
|
||||
@Configuration
|
||||
public class SaTokenConfigure {
|
||||
/**
|
||||
* 重写 Sa-Token 框架内部算法策略
|
||||
*/
|
||||
@Autowired
|
||||
public void rewriteSaStrategy() {
|
||||
// 重写 Token 生成策略
|
||||
SaStrategy.me.createToken = (loginId, loginType) -> {
|
||||
return SaFoxUtil.getRandomString(60); // 随机60位长度字符串
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -67,42 +64,3 @@ gfuPSwZsnUhwgz08GTCH4wOgasWtc3odP4HLwXJ7NDGOximTvT4OlW19zeLH
|
||||
```
|
||||
|
||||
|
||||
|
||||
<!-- ## 以雪花算法生成token
|
||||
在此再举一个例子,以`自定义token生成策略`的方式集成`雪花算法`来生成token -->
|
||||
|
||||
<!-- 1、首先我们需要找一个合适的类库,帮助我们生成雪花算法唯一id,在此推荐 [Hutool](https://hutool.cn/docs/#/) ,在`pom.xml`里添加依赖:
|
||||
``` xml
|
||||
Hutool 一个小而全的Java工具类库
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.5.4</version>
|
||||
</dependency>
|
||||
``` -->
|
||||
|
||||
<!-- 2、同上,我们需要新建文件`MySaTokenAction.java`,继承`SaTokenActionDefaultImpl`默认实现类, 并添加上注解`@Component`,保证此类被`springboot`扫描到
|
||||
``` java
|
||||
package com.pj.satoken;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import cn.dev33.satoken.action.SaTokenActionDefaultImpl;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
|
||||
/**
|
||||
* 继承Sa-Token行为Bean默认实现, 重写部分逻辑
|
||||
*/
|
||||
@Component
|
||||
public class MySaTokenAction extends SaTokenActionDefaultImpl {
|
||||
// 重写token生成策略
|
||||
@Override
|
||||
public String createToken(Object loginId, String loginType) {
|
||||
return IdUtil.getSnowflake(1, 1).nextIdStr(); // 以雪花算法生成token
|
||||
}
|
||||
}
|
||||
``` -->
|
||||
|
||||
<!-- 3、再次调用 `StpUtil.login(10001)`方法进行登录,观察其生成的token样式:
|
||||
``` html
|
||||
1339604338175250432
|
||||
``` -->
|
@ -89,14 +89,30 @@ public AjaxJson atJurOr() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
mode有两种取值:
|
||||
- `SaMode.AND`, 标注一组权限,会话必须全部具有才可通过校验
|
||||
- `SaMode.OR`, 标注一组权限,会话只要具有其一即可通过校验
|
||||
|
||||
|
||||
### 4、角色权限双重 “or校验”
|
||||
假设有以下业务场景:一个接口在具体权限 `user-add` 或角色 `admin` 时可以调通。怎么写?
|
||||
|
||||
### 4、在业务逻辑层使用注解鉴权
|
||||
``` java
|
||||
// 注解式鉴权:只要具有其中一个权限即可通过校验
|
||||
@RequestMapping("userAdd")
|
||||
@SaCheckPermission(value = "user-add", orRole = "admin")
|
||||
public AjaxJson userAdd() {
|
||||
return AjaxJson.getSuccessData("用户信息");
|
||||
}
|
||||
```
|
||||
|
||||
orRole 字段代表权限认证未通过时的次要选择,两者只要其一认证成功即可通过校验,其有三种写法:
|
||||
- 写法一:`orRole = "admin"`,代表需要拥有角色 admin 。
|
||||
- 写法二:`orRole = {"admin", "manager", "staff"}`,代表具有三个角色其一即可。
|
||||
- 写法三:`orRole = {"admin, manager, staff"}`,代表必须同时具有三个角色。
|
||||
|
||||
|
||||
### 5、在业务逻辑层使用注解鉴权
|
||||
疑问:我能否将注解写在其它架构层呢,比如业务逻辑层?
|
||||
|
||||
使用拦截器模式,只能在`Controller层`进行注解鉴权,如需在任意层级使用注解鉴权,请参考:[AOP注解鉴权](/plugin/aop-at)
|
||||
|
@ -33,7 +33,7 @@ sa-token:
|
||||
|
||||
|
||||
### 方式2、通过代码配置
|
||||
方式1:
|
||||
模式1:
|
||||
``` java
|
||||
/**
|
||||
* Sa-Token代码方式进行配置
|
||||
@ -59,7 +59,7 @@ public class SaTokenConfigure {
|
||||
}
|
||||
```
|
||||
|
||||
方式2:
|
||||
模式2:
|
||||
``` java
|
||||
// 以代码的方式配置Sa-Token-Config
|
||||
@Autowired
|
||||
@ -69,7 +69,7 @@ public void configSaToken(SaTokenConfig config) {
|
||||
}
|
||||
```
|
||||
|
||||
PS:两者的区别在于:**`方式1会覆盖yml中的配置,方式2会与yml中的配置合并`**
|
||||
PS:两者的区别在于:**`模式1会覆盖yml中的配置,模式2会与yml中的配置合并`**
|
||||
|
||||
|
||||
---
|
||||
@ -96,6 +96,18 @@ PS:两者的区别在于:**`方式1会覆盖yml中的配置,方式2会与y
|
||||
| basic | String | "" | Http Basic 认证的账号和密码 [参考:Http Basic 认证](/up/basic-auth) |
|
||||
| currDomain | null | "" | 配置当前项目的网络访问地址 |
|
||||
| sso | Object | new SaSsoConfig() | SSO 单点登录相关配置 |
|
||||
| cookie | Object | new SaCookieConfig() | Cookie配置对象 |
|
||||
|
||||
Cookie相关配置:
|
||||
|
||||
| 参数名称 | 类型 | 默认值 | 说明 |
|
||||
| :-------- | :-------- | :-------- | :-------- |
|
||||
| domain | String | null | 作用域(写入Cookie时显式指定的作用域, 常用于单点登录二级域名共享Cookie的场景) |
|
||||
| path | String | / | 路径,默认写在域名根路径下 |
|
||||
| secure | Boolean | false | 是否只在 https 协议下有效 |
|
||||
| httpOnly | Boolean | false | 是否禁止 js 操作 Cookie |
|
||||
| sameSite | String | Lax | 第三方限制级别(Strict=完全禁止,Lax=部分允许,None=不限制) |
|
||||
|
||||
|
||||
|
||||
### 单点登录相关配置
|
||||
@ -130,7 +142,7 @@ Client 端:
|
||||
sa-token:
|
||||
# SSO-相关配置
|
||||
sso:
|
||||
# SSO-Server端 单点登录地址
|
||||
# SSO-Server端 单点登录授权地址
|
||||
auth-url: http://sa-sso-server.com:9000/sso/auth
|
||||
```
|
||||
|
||||
|
@ -75,16 +75,16 @@ public class StpInterfaceImpl implements StpInterface {
|
||||
然后就可以用以下api来鉴权了
|
||||
|
||||
``` java
|
||||
// 当前账号是否含有指定权限, 返回true或false
|
||||
// 判断:当前账号是否含有指定权限, 返回true或false
|
||||
StpUtil.hasPermission("user-update");
|
||||
|
||||
// 当前账号是否含有指定权限, 如果验证未通过,则抛出异常: NotPermissionException
|
||||
// 校验:当前账号是否含有指定权限, 如果验证未通过,则抛出异常: NotPermissionException
|
||||
StpUtil.checkPermission("user-update");
|
||||
|
||||
// 当前账号是否含有指定权限 [指定多个,必须全部验证通过]
|
||||
// 校验:当前账号是否含有指定权限 [指定多个,必须全部验证通过]
|
||||
StpUtil.checkPermissionAnd("user-update", "user-delete");
|
||||
|
||||
// 当前账号是否含有指定权限 [指定多个,只要其一验证通过即可]
|
||||
// 校验:当前账号是否含有指定权限 [指定多个,只要其一验证通过即可]
|
||||
StpUtil.checkPermissionOr("user-update", "user-delete");
|
||||
```
|
||||
|
||||
@ -95,16 +95,16 @@ StpUtil.checkPermissionOr("user-update", "user-delete");
|
||||
在Sa-Token中,角色和权限可以独立验证
|
||||
|
||||
``` java
|
||||
// 当前账号是否含有指定角色标识, 返回true或false
|
||||
// 判断:当前账号是否拥有指定角色, 返回true或false
|
||||
StpUtil.hasRole("super-admin");
|
||||
|
||||
// 当前账号是否含有指定角色标识, 如果验证未通过,则抛出异常: NotRoleException
|
||||
// 校验:当前账号是否含有指定角色标识, 如果验证未通过,则抛出异常: NotRoleException
|
||||
StpUtil.checkRole("super-admin");
|
||||
|
||||
// 当前账号是否含有指定角色标识 [指定多个,必须全部验证通过]
|
||||
// 校验:当前账号是否含有指定角色标识 [指定多个,必须全部验证通过]
|
||||
StpUtil.checkRoleAnd("super-admin", "shop-admin");
|
||||
|
||||
// 当前账号是否含有指定角色标识 [指定多个,只要其一验证通过即可]
|
||||
// 校验:当前账号是否含有指定角色标识 [指定多个,只要其一验证通过即可]
|
||||
StpUtil.checkRoleOr("super-admin", "shop-admin");
|
||||
```
|
||||
|
||||
|
@ -6,25 +6,28 @@
|
||||
---
|
||||
|
||||
|
||||
### 根据账号id踢人
|
||||
让指定账号id的会话注销登录,例如:
|
||||
|
||||
### 1、强制注销
|
||||
``` java
|
||||
// 使账号id为10001的会话注销登录(踢人下线),待到10001再次访问系统时会抛出`NotLoginException`异常,场景值为-5
|
||||
StpUtil.logoutByLoginId(10001);
|
||||
StpUtil.logout(10001); // 强制指定账号注销下线
|
||||
StpUtil.logout(10001, "PC"); // 强制指定账号指定端注销下线
|
||||
StpUtil.logoutByTokenValue("token"); // 强制指定 Token 注销下线
|
||||
```
|
||||
|
||||
### 根据Token令牌踢人
|
||||
你还可以让指定token的会话注销登录
|
||||
|
||||
### 2、踢人下线
|
||||
``` java
|
||||
// 使账号id为10001的会话注销登录
|
||||
StpUtil.logoutByTokenValue("xxxx-xxxx-xxxx-xxxx-xxxx");
|
||||
StpUtil.kickout(10001); // 将指定账号踢下线
|
||||
StpUtil.kickout(10001, "PC"); // 将指定账号指定端踢下线
|
||||
StpUtil.kickoutByTokenValue("token"); // 将指定 Token 踢下线
|
||||
```
|
||||
此方法直接删除了`token->uid`的映射关系,对方再次访问时提示:`token无效`,场景值为-2
|
||||
|
||||
强制注销 和 踢人下线 的区别在于:
|
||||
- 强制注销等价于对方主动调用了注销方法,再次访问会提示:Token无效。
|
||||
- 踢人下线不会清除Token信息,而是将其打上特定标记,再次访问会提示:Token已被踢下线。
|
||||
|
||||
|
||||
|
||||
### 账号封禁
|
||||
### 3、账号封禁
|
||||
对于违规账号,有时候我们仅仅将其踢下线还是远远不够的,我们还需要对其进行**账号封禁**防止其再次登录
|
||||
|
||||
``` java
|
||||
@ -49,7 +52,7 @@ StpUtil.untieDisable(10001);
|
||||
如果需要将其封禁后立即掉线,可采取先踢再封禁的策略,例如:
|
||||
``` java
|
||||
// 先踢下线
|
||||
StpUtil.logoutByLoginId(10001);
|
||||
StpUtil.kickout(10001);
|
||||
// 再封禁账号
|
||||
StpUtil.disable(10001, 86400);
|
||||
```
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
|
||||
|
||||
### 1、注册路由拦截器
|
||||
### 1、注册 Sa-Token 路由拦截器
|
||||
以`SpringBoot2.0`为例, 新建配置类`SaTokenConfigure.java`
|
||||
``` java
|
||||
@Configuration
|
||||
@ -17,39 +17,44 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
||||
// 注册拦截器
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// 注册Sa-Token的路由拦截器,并排除登录接口或其他可匿名访问的接口地址 (与注解拦截器无关)
|
||||
registry.addInterceptor(new SaRouteInterceptor()).addPathPatterns("/**").excludePathPatterns("/user/doLogin");
|
||||
// 注册Sa-Token的路由拦截器
|
||||
registry.addInterceptor(new SaRouteInterceptor())
|
||||
.addPathPatterns("/**")
|
||||
.excludePathPatterns("/user/doLogin");
|
||||
}
|
||||
}
|
||||
```
|
||||
以上代码,我们注册了一个登录验证拦截器,并且排除了`/user/doLogin`接口用来开放登录(除了`/user/doLogin`以外的所有接口都需要登录才能访问) <br>
|
||||
以上代码,我们注册了一个登录认证拦截器,并且排除了`/user/doLogin`接口用来开放登录(除了`/user/doLogin`以外的所有接口都需要登录才能访问) <br>
|
||||
那么我们如何进行权限认证拦截呢,且往下看
|
||||
|
||||
|
||||
### 2、自定义权限验证规则
|
||||
你可以使用函数式编程自定义验证规则
|
||||
### 2、校验函数详解
|
||||
你可以使用函数式编程自定义认证规则,例如:
|
||||
|
||||
``` java
|
||||
@Configuration
|
||||
public class SaTokenConfigure implements WebMvcConfigurer {
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// 注册路由拦截器,自定义验证规则
|
||||
// 注册路由拦截器,自定义认证规则
|
||||
registry.addInterceptor(new SaRouteInterceptor((req, res, handler)->{
|
||||
// 根据路由划分模块,不同模块不同鉴权
|
||||
SaRouter.match("/user/**", () -> StpUtil.checkPermission("user"));
|
||||
SaRouter.match("/admin/**", () -> StpUtil.checkPermission("admin"));
|
||||
SaRouter.match("/goods/**", () -> StpUtil.checkPermission("goods"));
|
||||
SaRouter.match("/orders/**", () -> StpUtil.checkPermission("orders"));
|
||||
SaRouter.match("/notice/**", () -> StpUtil.checkPermission("notice"));
|
||||
SaRouter.match("/comment/**", () -> StpUtil.checkPermission("comment"));
|
||||
SaRouter.match("/user/**", r -> StpUtil.checkPermission("user"));
|
||||
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"));
|
||||
})).addPathPatterns("/**");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3、完整示例
|
||||
所有用法示例:
|
||||
SaRouter.match() 匹配函数有两个参数:
|
||||
- 参数一:要匹配的path路由。
|
||||
- 参数二:要执行的校验函数。
|
||||
|
||||
在校验函数内不只可以使用 `StpUtil.checkPermission("xxx")` 进行权限校验,你还可以写任意代码,例如:
|
||||
|
||||
``` java
|
||||
@Configuration
|
||||
@ -57,41 +62,28 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
||||
// 注册Sa-Token的拦截器
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// 注册路由拦截器,自定义验证规则
|
||||
// 注册路由拦截器,自定义认证规则
|
||||
registry.addInterceptor(new SaRouteInterceptor((req, res, handler) -> {
|
||||
|
||||
// 登录验证 -- 拦截所有路由,并排除/user/doLogin 用于开放登录
|
||||
SaRouter.match("/**", "/user/doLogin", () -> StpUtil.checkLogin());
|
||||
// 登录认证 -- 拦截所有路由,并排除/user/doLogin 用于开放登录
|
||||
SaRouter.match("/**", "/user/doLogin", r -> StpUtil.checkLogin());
|
||||
|
||||
// 角色认证 -- 拦截以 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"));
|
||||
SaRouter.match("/orders/**", r -> StpUtil.checkPermission("orders"));
|
||||
SaRouter.match("/notice/**", r -> StpUtil.checkPermission("notice"));
|
||||
SaRouter.match("/comment/**", r -> StpUtil.checkPermission("comment"));
|
||||
|
||||
// 登录验证 -- 排除多个路径
|
||||
SaRouter.match(Arrays.asList("/**"), Arrays.asList("/user/doLogin", "/user/reg"), () -> StpUtil.checkLogin());
|
||||
|
||||
// 角色认证 -- 拦截以 admin 开头的路由,必须具备[admin]角色或者[super-admin]角色才可以通过认证
|
||||
SaRouter.match("/admin/**", () -> StpUtil.checkRoleOr("admin", "super-admin"));
|
||||
|
||||
// 权限认证 -- 不同模块, 校验不同权限
|
||||
SaRouter.match("/user/**", () -> StpUtil.checkPermission("user"));
|
||||
SaRouter.match("/admin/**", () -> StpUtil.checkPermission("admin"));
|
||||
SaRouter.match("/goods/**", () -> StpUtil.checkPermission("goods"));
|
||||
SaRouter.match("/orders/**", () -> StpUtil.checkPermission("orders"));
|
||||
SaRouter.match("/notice/**", () -> StpUtil.checkPermission("notice"));
|
||||
SaRouter.match("/comment/**", () -> StpUtil.checkPermission("comment"));
|
||||
|
||||
// 匹配 restful 风格路由
|
||||
SaRouter.match("/article/get/{id}", () -> StpUtil.checkPermission("article"));
|
||||
|
||||
// 检查请求方式
|
||||
SaRouter.match("/notice/**", () -> {
|
||||
if(req.getMethod().equals(HttpMethod.GET.toString())) {
|
||||
StpUtil.checkPermission("notice");
|
||||
}
|
||||
});
|
||||
|
||||
// 提前退出 (执行SaRouter.stop()后会直接退出匹配链)
|
||||
SaRouter.match("/test/back", () -> SaRouter.stop());
|
||||
|
||||
// 在多账号模式下,可以使用任意StpUtil进行校验
|
||||
SaRouter.match("/user/**", () -> StpUserUtil.checkLogin());
|
||||
// 甚至你可以随意的写一个打印语句
|
||||
SaRouter.match("/**", r -> System.out.println("----啦啦啦----"));
|
||||
|
||||
// 连缀写法
|
||||
SaRouter.match("/**").check(r -> System.out.println("----啦啦啦----"));
|
||||
|
||||
})).addPathPatterns("/**");
|
||||
}
|
||||
@ -99,44 +91,80 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
||||
```
|
||||
|
||||
|
||||
### 4、提前退出匹配链条
|
||||
### 3、匹配特征详解
|
||||
|
||||
除了上述示例的 path 路由匹配,还可以根据很多其它特征进行匹配,以下是所有可匹配的特征:
|
||||
|
||||
``` java
|
||||
// 基础写法样例:匹配一个path,执行一个校验函数
|
||||
SaRouter.match("/user/**").check(r -> StpUtil.checkLogin());
|
||||
|
||||
// 根据 path 路由匹配 ——— 支持写多个path,支持写 restful 风格路由
|
||||
SaRouter.match("/user/**", "/goods/**", "/art/get/{id}").check( /* 要执行的校验函数 */ );
|
||||
|
||||
// 根据 path 路由排除匹配
|
||||
SaRouter.match("/**").notMatch("*.html", "*.css", "*.js").check( /* 要执行的校验函数 */ );
|
||||
|
||||
// 根据请求类型匹配
|
||||
SaRouter.match(SaHttpMethod.GET).check( /* 要执行的校验函数 */ );
|
||||
|
||||
// 根据一个 boolean 条件进行匹配
|
||||
SaRouter.match( StpUtil.isLogin() ).check( /* 要执行的校验函数 */ );
|
||||
|
||||
// 根据一个返回 boolean 结果的lambda表达式匹配
|
||||
SaRouter.match( r -> StpUtil.isLogin() ).check( /* 要执行的校验函数 */ );
|
||||
|
||||
// 多个条件一起使用
|
||||
SaRouter.match(SaHttpMethod.GET).match("/**").check( /* 要执行的校验函数 */ );
|
||||
|
||||
// 可以无限连缀下去
|
||||
SaRouter
|
||||
.match(SaHttpMethod.GET)
|
||||
.match("/admin/**")
|
||||
.match("/user/**")
|
||||
.notMatch("/**/*.js")
|
||||
.notMatch("/**/*.css")
|
||||
// ....
|
||||
.check( /* 只有上述所有条件都匹配成功,才会执行最后的check校验函数 */ );
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 4、提前退出匹配链
|
||||
使用 `SaRouter.stop()` 可以提前退出匹配链,例:
|
||||
|
||||
``` java
|
||||
registry.addInterceptor(new SaRouteInterceptor((req, res, handler) -> {
|
||||
SaRouter.match("/**", () -> System.out.println("进入1"));
|
||||
SaRouter.match("/**", () -> {System.out.println("进入2"); SaRouter.stop();});
|
||||
SaRouter.match("/**", () -> System.out.println("进入3"));
|
||||
SaRouter.match("/**").check(r -> System.out.println("进入1"));
|
||||
SaRouter.match("/**").check(r -> System.out.println("进入2")).stop();
|
||||
SaRouter.match("/**").check(r -> System.out.println("进入3"));
|
||||
})).addPathPatterns("/**");
|
||||
```
|
||||
如上示例,代码运行至第2条匹配链时,会在stop函数处提前退出整个匹配函数,从而忽略掉剩余的所有match匹配
|
||||
|
||||
除了`stop()`函数,`SaRouter`还提供了 `back()` 函数,用于:停止匹配,结束执行,直接向前端返回结果
|
||||
``` java
|
||||
SaRouter.match("/user/back", () -> SaRouter.back("执行back函数后将停止匹配,也不会进入Controller,而是直接将此参数作为返回值输出到前端"));
|
||||
// 执行back函数后将停止匹配,也不会进入Controller,而是直接将 back参数 作为返回值输出到前端
|
||||
SaRouter.match("/user/back").back("参数");
|
||||
```
|
||||
|
||||
`stop()` 与 `back()` 函数的区别在于:
|
||||
stop() 与 back() 函数的区别在于:
|
||||
- `SaRouter.stop()` 会停止匹配,进入Controller。
|
||||
- `SaRouter.back()` 会停止匹配,直接返回结果到前端。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
### 注意事项
|
||||
在`v1.14`及以前版本下,路由拦截器提供了封装式写法,该方法代码比较冗余,在`v1.15`版本已移除,替代方案如下:
|
||||
### 5、使用free打开一个独立的作用域
|
||||
|
||||
``` java
|
||||
// 原写法
|
||||
registry.addInterceptor(SaRouteInterceptor.createPermissionVal("user")).addPathPatterns("/user/**");
|
||||
|
||||
// 改为以下方式,效果同上
|
||||
registry.addInterceptor(new SaRouteInterceptor((request, response, handler) -> {
|
||||
SaRouter.match("/user/**", () -> StpUtil.checkPermission("user"));
|
||||
})).addPathPatterns("/**");
|
||||
// 进入 free 独立作用域
|
||||
SaRouter.match("/**").free(r -> {
|
||||
SaRouter.match("/a/**").check(/* --- */);
|
||||
SaRouter.match("/a/**").check(/* --- */).stop();
|
||||
SaRouter.match("/a/**").check(/* --- */);
|
||||
});
|
||||
// 执行 stop() 函数跳出 free 后继续执行下面的 match 匹配
|
||||
SaRouter.match("/**").check(/* --- */);
|
||||
```
|
||||
-->
|
||||
|
||||
|
||||
|
||||
free() 的作用是:打开一个独立的作用域,使内部的 stop() 不再一次性跳出整个 Auth 函数,而是仅仅跳出当前 free 作用域。
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user