优化文档

This commit is contained in:
click33 2023-06-21 23:10:29 +08:00
parent a05b4af075
commit f344d7fda8
12 changed files with 84 additions and 79 deletions

View File

@ -143,7 +143,7 @@ public class SaOAuth2ServerController {
public class SaOAuth2ServerApplication {
public static void main(String[] args) {
SpringApplication.run(SaOAuth2ServerApplication.class, args);
System.out.println("\nSa-Token-OAuth Server端启动成功");
System.out.println("\nSa-Token-OAuth Server 端启动成功");
}
}
```

View File

@ -16,7 +16,7 @@
<!---------------------------- tabs:start ---------------------------->
<!-------- tab:Maven 方式 -------->
注:如果你使用的是 `SpringBoot 3.x`,只需要将 `sa-token-spring-boot-starter` 修改为 `sa-token-spring-boot3-starter` 即可。
注:如果你使用的是 SpringBoot 3.x只需要将 `sa-token-spring-boot-starter` 修改为 `sa-token-spring-boot3-starter` 即可。
``` xml
<!-- Sa-Token 权限认证在线文档https://sa-token.cc -->
@ -29,7 +29,7 @@
<!-------- tab:Gradle 方式 -------->
注:如果你使用的是 `SpringBoot 3.x`,只需要将 `sa-token-spring-boot-starter` 修改为 `sa-token-spring-boot3-starter` 即可。
注:如果你使用的是 SpringBoot 3.x只需要将 `sa-token-spring-boot-starter` 修改为 `sa-token-spring-boot3-starter` 即可。
``` gradle
// Sa-Token 权限认证在线文档https://sa-token.cc
@ -105,7 +105,7 @@ sa-token.is-log=true
public class SaTokenDemoApplication {
public static void main(String[] args) throws JsonProcessingException {
SpringApplication.run(SaTokenDemoApplication.class, args);
System.out.println("启动成功Sa-Token配置如下:" + SaManager.getConfig());
System.out.println("启动成功Sa-Token 配置如下:" + SaManager.getConfig());
}
}
```
@ -149,8 +149,8 @@ public class UserController {
-->
### 详细了解
通过这个示例,你已经对 Sa-Token 有了初步的了解,那么现在开始详细了解一下它都有哪些吧:[登录认证](/use/login-auth)
### 出发
通过这个示例,你已经对 Sa-Token 有了初步的了解。那么,坐稳扶好,让我们开始吧:[登录认证](/use/login-auth)

View File

@ -2,7 +2,7 @@
本篇介绍在 Solon 应用中如何集成 Sa-Token。
整合示例在官方仓库的 /sa-token-demo/sa-token-demo-solon 文件夹下,如遇到难点可结合源码进行学习测试。
整合示例在官方仓库的 `/sa-token-demo/sa-token-demo-solon` 文件夹下,如遇到难点可结合源码进行学习测试。
> Solon 是一个高效的国产应用开发框架:更快、更小、更简单。
>
@ -119,7 +119,7 @@ sa-token.is-log=true
public class SaTokenDemoApp {
public static void main(String[] args) {
Solon.start(SaTokenDemoApp.class, args);
System.out.println("启动成功Sa-Token配置如下:" + SaManager.getConfig());
System.out.println("启动成功Sa-Token 配置如下:" + SaManager.getConfig());
}
}
```

View File

@ -48,7 +48,7 @@ implementation 'cn.dev33:sa-token-reactor-spring-boot-starter:${sa.top.version}'
public class SaTokenDemoApplication {
public static void main(String[] args) throws JsonProcessingException {
SpringApplication.run(SaTokenDemoApplication.class, args);
System.out.println("启动成功Sa-Token配置如下:" + SaManager.getConfig());
System.out.println("启动成功Sa-Token 配置如下:" + SaManager.getConfig());
}
}
```

View File

@ -6,10 +6,10 @@ Sa-Token 默认将数据保存在内存中,此模式读写速度最快,且
1. 重启后数据会丢失。
2. 无法在分布式环境中共享数据。
为此Sa-Token 提供了扩展接口,你可以轻松将会话数据存储在 `Redis`、`Memcached`等专业的缓存中间件中
为此Sa-Token 提供了扩展接口,你可以轻松将会话数据存储在一些专业的缓存中间件上(比如 Redis
做到重启数据不丢失,而且保证分布式环境下多节点的会话一致性。
以下是官方提供的 Redis 集成包:
以下是框架提供的 Redis 集成包:
---

View File

@ -26,7 +26,7 @@
而如果我们深入它的源码,[点此阅览](https://gitee.com/dromara/sa-token/blob/master/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java) <br/>
就会发现,此类并没有任何代码逻辑,唯一做的事就是对成员变量`stpLogic`的各个API包装一下进行转发。
这样做有两个优点:
这样做有两个好处:
- StpLogic 类的所有函数都可以被重写,按需扩展。
- 在构造方法时随意传入一个不同的 `loginType`,就可以再造一套账号登录体系。

View File

@ -7,8 +7,8 @@
## 内置风格
Sa-Token默认的token生成策略是uuid风格其模样类似于`623368f0-ae5e-4475-a53f-93e4225f16ae`。<br>
如果你对这种风格不太感冒还可以将token生成设置为其他风格。
Sa-Token 默认的 token 生成策略是 uuid 风格,其模样类似于:`623368f0-ae5e-4475-a53f-93e4225f16ae`。<br>
如果你对这种风格不太感冒,还可以将 token 生成设置为其他风格。
怎么设置呢只需要在yml配置文件里设置 `sa-token.token-style=风格类型` 即可,其有多种取值:

View File

@ -100,8 +100,8 @@ public SaResult atJurOr() {
```
mode有两种取值
- `SaMode.AND`, 标注一组权限,会话必须全部具有才可通过校验。
- `SaMode.OR`, 标注一组权限,会话只要具有其一即可通过校验。
- `SaMode.AND`标注一组权限,会话必须全部具有才可通过校验。
- `SaMode.OR`标注一组权限,会话只要具有其一即可通过校验。
### 4、角色权限双重 “or校验”
@ -116,7 +116,7 @@ public SaResult userAdd() {
}
```
orRole 字段代表权限认证未通过时的次要选择,两者只要其一认证成功即可通过校验,其有三种写法:
orRole 字段代表权限校验未通过时的次要选择,两者只要其一校验成功即可进入请求方法,其有三种写法:
- 写法一:`orRole = "admin"`,代表需要拥有角色 admin 。
- 写法二:`orRole = {"admin", "manager", "staff"}`,代表具有三个角色其一即可。
- 写法三:`orRole = {"admin, manager, staff"}`,代表必须同时具有三个角色。

View File

@ -2,14 +2,13 @@
---
### 设计思路
### 1、设计思路
所谓权限认证,核心逻辑就是判断一个账号是否拥有指定权限:<br/>
- 有,就让你通过。
- 没有?那么禁止访问!
深入到底层数据中,就是每个账号都会拥有一权限码集合,框架来校验这个集合中是否包含指定的权限码。
深入到底层数据中,就是每个账号都会拥有一权限码集合,框架来校验这个集合中是否包含指定的权限码。
例如:当前账号拥有权限码集合 `["user-add", "user-delete", "user-get"]`,这时候我来校验权限 `"user-update"`,则其结果就是:**验证失败,禁止访问**。 <br/>
@ -17,11 +16,12 @@
<button class="show-img" img-src="https://oss.dev33.cn/sa-token/doc/g/g3--jur-auth.gif">加载动态演示图</button>
所以现在问题的核心就是:
1. 如何获取一个账号所拥有的权限码集合?
所以现在问题的核心就是两个
1. 如何获取一个账号所拥有的权限码集合?
2. 本次操作需要验证的权限码是哪个?
### 获取当前账号权限码集合
### 2、获取当前账号权限码集合
因为每个项目的需求不同,其权限设计也千变万化,因此 [ 获取当前账号权限码集合 ] 这一操作不可能内置到框架中,
所以 Sa-Token 将此操作以接口的方式暴露给你,以方便你根据自己的业务逻辑进行重写。
@ -29,9 +29,9 @@
``` java
/**
* 自定义权限验证接口扩展
* 自定义权限加载接口实现类
*/
@Component // 保证此类被SpringBoot扫描完成Sa-Token的自定义权限验证扩展
@Component // 保证此类被 SpringBoot 扫描,完成 Sa-Token 的自定义权限验证扩展
public class StpInterfaceImpl implements StpInterface {
/**
@ -39,7 +39,7 @@ public class StpInterfaceImpl implements StpInterface {
*/
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
// 本list仅做模拟实际项目中要根据具体业务逻辑来查询权限
// 本 list 仅做模拟,实际项目中要根据具体业务逻辑来查询权限
List<String> list = new ArrayList<String>();
list.add("101");
list.add("user.add");
@ -55,7 +55,7 @@ public class StpInterfaceImpl implements StpInterface {
*/
@Override
public List<String> getRoleList(Object loginId, String loginType) {
// 本list仅做模拟实际项目中要根据具体业务逻辑来查询角色
// 本 list 仅做模拟,实际项目中要根据具体业务逻辑来查询角色
List<String> list = new ArrayList<String>();
list.add("admin");
list.add("super-admin");
@ -71,11 +71,12 @@ public class StpInterfaceImpl implements StpInterface {
可参考代码:[码云StpInterfaceImpl.java](https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/StpInterfaceImpl.java)
> 注意: StpInterface 接口在需要鉴权时由框架自动调用,开发者只需要配置好就可以使用下面的鉴权方法或后面的注解鉴权
> 有同学会产生疑问:我实现了此接口,但是程序启动时好像并没有执行,是不是我写错了?
> 答:不执行是正常现象,程序启动时不会执行这个接口的方法,在每次调用鉴权代码时,才会执行到此。
### 权限校验
然后就可以用以下api来鉴权了
### 3、权限校验
然后就可以用以下 api 来鉴权了
``` java
// 获取:当前账号所拥有的权限集合
@ -97,8 +98,8 @@ StpUtil.checkPermissionOr("user.add", "user.delete", "user.get");
扩展:`NotPermissionException` 对象可通过 `getLoginType()` 方法获取具体是哪个 `StpLogic` 抛出的异常
### 角色校验
在Sa-Token中角色和权限可以独立验证
### 4、角色校验
Sa-Token 中,角色和权限可以分开独立验证
``` java
// 获取:当前账号所拥有的角色集合
@ -121,7 +122,7 @@ StpUtil.checkRoleOr("super-admin", "shop-admin");
### 拦截全局异常
### 5、拦截全局异常
有同学要问,鉴权失败,抛出异常,然后呢?要把异常显示给用户看吗?**当然不可以!**
你可以创建一个全局异常拦截器,统一返回给前端的格式,参考:
@ -141,7 +142,7 @@ public class GlobalExceptionHandler {
可参考:[码云GlobalException.java](https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/current/GlobalException.java)
### 权限通配符
### 6、权限通配符
Sa-Token允许你根据通配符指定**泛权限**,例如当一个账号拥有`art.*`的权限时,`art.add`、`art.delete`、`art.update`都将匹配通过
``` java
@ -164,7 +165,7 @@ StpUtil.hasPermission("index.html"); // false
!> 上帝权限:当一个账号拥有 `"*"` 权限时,他可以验证通过任何权限码 (角色认证同理)
### 如何把权限精确到按钮级?
### 7、如何把权限精确到按钮级?
权限精确到按钮级的意思就是指:**权限范围可以控制到页面上的每一个按钮是否显示**。
思路:如此精确的范围控制只依赖后端已经难以完成,此时需要前端进行一定的逻辑判断。
@ -183,10 +184,11 @@ StpUtil.hasPermission("index.html"); // false
注意:以上写法只为提供一个参考示例,不同框架有不同写法,大家可根据项目技术栈灵活封装进行调用。
### 前端有了鉴权后端还需要鉴权吗?
### 8、前端有了鉴权后端还需要鉴权吗?
**需要!**
前端的鉴权只是一个辅助功能,对于专业人员这些限制都是可以轻松绕过的,为保证服务器安全,无论前端是否进行了权限校验,后端接口都需要对会话请求再次进行权限校验!
前端的鉴权只是一个辅助功能,对于专业人员这些限制都是可以轻松绕过的,
为保证服务器安全,**无论前端是否进行了权限校验,后端接口都需要对会话请求再次进行权限校验!**

View File

@ -3,7 +3,7 @@
---
### 设计思路
### 1、设计思路
对于一些登录之后才能访问的接口(例如:查询我的账号资料),我们通常的做法是增加一层接口校验:
@ -23,7 +23,7 @@
<button class="show-img" img-src="https://oss.dev33.cn/sa-token/doc/g/g3--login-auth.gif">加载动态演示图</button>
### 登录与注销
### 2、登录与注销
根据以上思路,我们需要一个会话登录的函数:
``` java
@ -33,13 +33,14 @@ StpUtil.login(Object id);
只此一句代码便可以使会话登录成功实际上Sa-Token 在背后做了大量的工作,包括但不限于:
1. 检查此账号是否之前已有登录
2. 为账号生成 `Token` 凭证与 `Session` 会话
3. 通知全局侦听器xx 账号登录成功
4. 将 `Token` 注入到请求上下文
5. 等等其它工作……
1. 检查此账号是否之前已有登录;
2. 为账号生成 `Token` 凭证与 `Session` 会话;
3. 记录 Token 活跃时间;
4. 通知全局侦听器xx 账号登录成功;
5. 将 `Token` 注入到请求上下文;
6. 等等其它工作……
你暂时不需要完整了解整个登录过程,你只需要记住关键一点:`Sa-Token 为这个账号创建了一个Token凭证且通过 Cookie 上下文返回给了前端`。
你暂时不需要完整了解整个登录过程,你只需要记住关键一点:`Sa-Token 为这个账号创建了一个Token凭证且通过 Cookie 上下文返回给了前端`。
所以一般情况下,我们的登录接口代码,会大致类似如下:
@ -57,13 +58,13 @@ public SaResult doLogin(String name, String pwd) {
}
```
如果你对以上代码阅读没有压力,你可能会注意到略显奇怪的一点:此处仅仅做了会话登录,但并没有主动向前端返回 Token 信息。
是因为不需要吗?严格来讲是需要的,只不过 `StpUtil.login(id)` 方法利用了 Cookie 自动注入的特性,省略了你手写返回 Token 的代码。
如果你对以上代码阅读没有压力,你可能会注意到略显奇怪的一点:此处仅仅做了会话登录,但并没有主动向前端返回 token 信息。
是因为不需要吗?严格来讲是需要的,只不过 `StpUtil.login(id)` 方法利用了 Cookie 自动注入的特性,省略了你手写返回 token 的代码。
如果你对 Cookie 功能还不太了解,也不用担心,我们会在之后的 [ 前后端分离 ] 章节中详细的阐述 Cookie 功能,现在你只需要了解最基本的两点:
- Cookie 可以从后端控制往浏览器中写入 Token 值。
- Cookie 会在前端每次发起请求时自动提交 Token 值。
- Cookie 可以从后端控制往浏览器中写入 token 值。
- Cookie 会在前端每次发起请求时自动提交 token 值。
因此,在 Cookie 功能的加持下,我们可以仅靠 `StpUtil.login(id)` 一句代码就完成登录认证。
@ -81,10 +82,10 @@ StpUtil.checkLogin();
```
异常 `NotLoginException` 代表当前会话暂未登录,可能的原因有很多:
前端没有提交 Token、前端提交的 Token 是无效的、前端提交的 Token 已经过期 …… 等等,可参照此篇:[未登录场景值](/fun/not-login-scene),了解如何获取未登录的场景值。
前端没有提交 token、前端提交的 token 是无效的、前端提交的 token 已经过期 …… 等等,可参照此篇:[未登录场景值](/fun/not-login-scene),了解如何获取未登录的场景值。
### 会话查询
### 3、会话查询
``` java
// 获取当前会话账号id, 如果未登录,则抛出异常:`NotLoginException`
StpUtil.getLoginId();
@ -96,7 +97,7 @@ StpUtil.getLoginIdAsLong(); // 获取当前会话账号id, 并转化为`lon
// ---------- 指定未登录情形下返回的默认值 ----------
// 获取当前会话账号id, 如果未登录则返回null
// 获取当前会话账号id, 如果未登录,则返回 null
StpUtil.getLoginIdDefaultNull();
// 获取当前会话账号id, 如果未登录,则返回默认值 `defaultValue`可以为任意类型)
@ -104,29 +105,29 @@ StpUtil.getLoginId(T defaultValue);
```
### Token 查询
### 4、token 查询
``` java
// 获取当前会话的token值
// 获取当前会话的 token
StpUtil.getTokenValue();
// 获取当前`StpLogic`的token名称
// 获取当前`StpLogic`的 token 名称
StpUtil.getTokenName();
// 获取指定token对应的账号id如果未登录则返回 null
// 获取指定 token 对应的账号id如果未登录则返回 null
StpUtil.getLoginIdByToken(String tokenValue);
// 获取当前会话剩余有效期单位s返回-1代表永久有效
StpUtil.getTokenTimeout();
// 获取当前会话的token信息参数
// 获取当前会话的 token 信息参数
StpUtil.getTokenInfo();
```
有关`TokenInfo`参数详解,请参考:[TokenInfo参数详解](/fun/token-info)
### 来个小测试,加深一下理解
新建 `LoginController`,复制以下代码
### 5、来个小测试,加深一下理解
新建 `LoginController`,复制或手动敲出以下代码
``` java
/**
* 登录测试

View File

@ -7,12 +7,12 @@
我们怎么实现呢?给每个接口加上鉴权注解?手写全局拦截器?似乎都不是非常方便。
在这个需求中我们真正需要的是一种基于路由拦截的鉴权模式, 那么在Sa-Token怎么实现路由拦截鉴权呢
在这个需求中我们真正需要的是一种基于路由拦截的鉴权模式那么在Sa-Token怎么实现路由拦截鉴权呢
### 1、注册 Sa-Token 路由拦截器
以`SpringBoot2.0`为例, 新建配置类`SaTokenConfigure.java`
以`SpringBoot2.0`为例新建配置类`SaTokenConfigure.java`
``` java
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {

View File

@ -2,15 +2,15 @@
---
### Session是什么
### 1、Session是什么
Session是会话中专业的数据缓存组件通过 Session 我们可以很方便的缓存一些高频读写数据,提高程序性能,例如:
Session 是会话中专业的数据缓存组件,通过 Session 我们可以很方便的缓存一些高频读写数据,提高程序性能,例如:
``` java
// 在登录时缓存user对象
// 在登录时缓存 user 对象
StpUtil.getSession().set("user", user);
// 然后我们就可以在任意处使用这个user对象
// 然后我们就可以在任意处使用这个 user 对象
SysUser user = (SysUser) StpUtil.getSession().get("user");
```
@ -20,31 +20,31 @@ SysUser user = (SysUser) StpUtil.getSession().get("user");
- `Token-Session`: 指的是框架为每个 token 分配的 Session
- `Custom-Session`: 指的是以一个 特定的值 作为SessionId来分配的 Session
> 有关Account-Session与Token-Session的详细区别可参考[Session模型详解](/fun/session-model)
> 有关 Account-Session Token-Session 的详细区别,可参考:[Session模型详解](/fun/session-model)
### Account-Session
有关账号Session的API如下
有关 账号-Session API 如下:
``` java
// 获取当前账号id的Session (必须是登录后才能调用)
// 获取当前账号 id Account-Session (必须是登录后才能调用)
StpUtil.getSession();
// 获取当前账号id的Session, 并决定在Session尚未创建时是否新建并返回
// 获取当前账号 id Account-Session, 并决定在 Session 尚未创建时,是否新建并返回
StpUtil.getSession(true);
// 获取账号id为10001的Session
// 获取账号 id 10001 Account-Session
StpUtil.getSessionByLoginId(10001);
// 获取账号id为10001的Session, 并决定在Session尚未创建时是否新建并返回
// 获取账号 id 10001 Account-Session, 并决定在 Session 尚未创建时,是否新建并返回
StpUtil.getSessionByLoginId(10001, true);
// 获取SessionId为xxxx-xxxx的Session, 在Session尚未创建时, 返回null
// 获取 SessionId xxxx-xxxx Account-Session, 在 Session 尚未创建时, 返回 null
StpUtil.getSessionBySessionId("xxxx-xxxx");
```
### Token-Session
有关令牌Session的API如下
有关 令牌-Session API 如下:
``` java
// 获取当前 Token 的 Token-Session 对象
StpUtil.getTokenSession();
@ -54,9 +54,9 @@ StpUtil.getTokenSessionByToken(token);
```
### 自定义Session
自定义Session指的是以一个`特定的值`作为SessionId来分配的`Session`, 借助自定义Session你可以为系统中的任意元素分配相应的session<br>
例如以商品id作为key为每个商品分配一个Session以便于缓存和商品相关的数据其相关API如下
### Custom-Session
自定义 Session 指的是以一个`特定的值`作为 SessionId 来分配的`Session`, 借助自定义Session你可以为系统中的任意元素分配相应的session<br>
例如以商品 id 作为 key 为每个商品分配一个Session以便于缓存和商品相关的数据其相关API如下
``` java
// 查询指定key的Session是否存在
SaSessionCustomUtil.isExists("goods-10001");
@ -74,6 +74,8 @@ SaSessionCustomUtil.deleteSessionById("goods-10001");
### 在 Session 上存取值
以上三种 Session 均为框架设计概念上的区分,实际上在获取它们时,返回的都是 SaSession 对象,你可以使用以下 API 在 SaSession 对象上存取值:
``` java
// 写值
session.set("name", "zhang");
@ -101,7 +103,7 @@ session.getFloat("result"); // 取值 (转float类型)
session.getModel("key", Student.class); // 取值 (指定转换类型)
session.getModel("key", Student.class, <defaultValue>); // 取值 (指定转换类型, 并指定值为Null时返回的默认值)
// 是否含有某个key (返回true或false)
// 是否含有某个key (返回 true false)
session.has("key");
// 删值
@ -135,8 +137,8 @@ session.logout();
```
### Session环境隔离说明
有同学经常会把 `SaSession``HttpSession` 进行混淆,例如:
### 避免与 HttpSession 混淆使用
经常有同学会把 `SaSession``HttpSession` 进行混淆,例如:
``` java
@PostMapping("/resetPoints")
public void reset(HttpSession session) {