diff --git a/sa-token-doc/oauth2/oauth2-server.md b/sa-token-doc/oauth2/oauth2-server.md index fc48d79b..9f2b631f 100644 --- a/sa-token-doc/oauth2/oauth2-server.md +++ b/sa-token-doc/oauth2/oauth2-server.md @@ -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 端启动成功"); } } ``` diff --git a/sa-token-doc/start/example.md b/sa-token-doc/start/example.md index 6be60871..9cf43459 100644 --- a/sa-token-doc/start/example.md +++ b/sa-token-doc/start/example.md @@ -16,7 +16,7 @@ -注:如果你使用的是 `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 @@ -29,7 +29,7 @@ -注:如果你使用的是 `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) diff --git a/sa-token-doc/start/solon-example.md b/sa-token-doc/start/solon-example.md index c31a989f..d374e02a 100644 --- a/sa-token-doc/start/solon-example.md +++ b/sa-token-doc/start/solon-example.md @@ -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()); } } ``` diff --git a/sa-token-doc/start/webflux-example.md b/sa-token-doc/start/webflux-example.md index 649f248a..fa43e661 100644 --- a/sa-token-doc/start/webflux-example.md +++ b/sa-token-doc/start/webflux-example.md @@ -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()); } } ``` diff --git a/sa-token-doc/up/integ-redis.md b/sa-token-doc/up/integ-redis.md index 43d66bb8..54191e43 100644 --- a/sa-token-doc/up/integ-redis.md +++ b/sa-token-doc/up/integ-redis.md @@ -6,10 +6,10 @@ Sa-Token 默认将数据保存在内存中,此模式读写速度最快,且 1. 重启后数据会丢失。 2. 无法在分布式环境中共享数据。 -为此,Sa-Token 提供了扩展接口,你可以轻松将会话数据存储在 `Redis`、`Memcached`等专业的缓存中间件中, +为此,Sa-Token 提供了扩展接口,你可以轻松将会话数据存储在一些专业的缓存中间件上(比如 Redis), 做到重启数据不丢失,而且保证分布式环境下多节点的会话一致性。 -以下是官方提供的 Redis 集成包: +以下是框架提供的 Redis 集成包: --- diff --git a/sa-token-doc/up/many-account.md b/sa-token-doc/up/many-account.md index cad8c732..406c4ad7 100644 --- a/sa-token-doc/up/many-account.md +++ b/sa-token-doc/up/many-account.md @@ -26,7 +26,7 @@ 而如果我们深入它的源码,[点此阅览](https://gitee.com/dromara/sa-token/blob/master/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java)
就会发现,此类并没有任何代码逻辑,唯一做的事就是对成员变量`stpLogic`的各个API包装一下进行转发。 -这样做有两个优点: +这样做有两个好处: - StpLogic 类的所有函数都可以被重写,按需扩展。 - 在构造方法时随意传入一个不同的 `loginType`,就可以再造一套账号登录体系。 diff --git a/sa-token-doc/up/token-style.md b/sa-token-doc/up/token-style.md index d0179ec0..0b5eee5f 100644 --- a/sa-token-doc/up/token-style.md +++ b/sa-token-doc/up/token-style.md @@ -7,8 +7,8 @@ ## 内置风格 -Sa-Token默认的token生成策略是uuid风格,其模样类似于:`623368f0-ae5e-4475-a53f-93e4225f16ae`。
-如果你对这种风格不太感冒,还可以将token生成设置为其他风格。 +Sa-Token 默认的 token 生成策略是 uuid 风格,其模样类似于:`623368f0-ae5e-4475-a53f-93e4225f16ae`。
+如果你对这种风格不太感冒,还可以将 token 生成设置为其他风格。 怎么设置呢?只需要在yml配置文件里设置 `sa-token.token-style=风格类型` 即可,其有多种取值: diff --git a/sa-token-doc/use/at-check.md b/sa-token-doc/use/at-check.md index 42f432c7..ac2d33d1 100644 --- a/sa-token-doc/use/at-check.md +++ b/sa-token-doc/use/at-check.md @@ -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"}`,代表必须同时具有三个角色。 diff --git a/sa-token-doc/use/jur-auth.md b/sa-token-doc/use/jur-auth.md index 3b6be1b7..4989c6b2 100644 --- a/sa-token-doc/use/jur-auth.md +++ b/sa-token-doc/use/jur-auth.md @@ -2,14 +2,13 @@ --- - -### 设计思路 +### 1、设计思路 所谓权限认证,核心逻辑就是判断一个账号是否拥有指定权限:
- 有,就让你通过。 - 没有?那么禁止访问! -深入到底层数据中,就是每个账号都会拥有一个权限码集合,框架来校验这个集合中是否包含指定的权限码。 +深入到底层数据中,就是每个账号都会拥有一组权限码集合,框架来校验这个集合中是否包含指定的权限码。 例如:当前账号拥有权限码集合 `["user-add", "user-delete", "user-get"]`,这时候我来校验权限 `"user-update"`,则其结果就是:**验证失败,禁止访问**。
@@ -17,11 +16,12 @@ -所以现在问题的核心就是: -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 getPermissionList(Object loginId, String loginType) { - // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限 + // 本 list 仅做模拟,实际项目中要根据具体业务逻辑来查询权限 List list = new ArrayList(); list.add("101"); list.add("user.add"); @@ -55,7 +55,7 @@ public class StpInterfaceImpl implements StpInterface { */ @Override public List getRoleList(Object loginId, String loginType) { - // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询角色 + // 本 list 仅做模拟,实际项目中要根据具体业务逻辑来查询角色 List list = new ArrayList(); 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、前端有了鉴权后端还需要鉴权吗? **需要!** -前端的鉴权只是一个辅助功能,对于专业人员这些限制都是可以轻松绕过的,为保证服务器安全,无论前端是否进行了权限校验,后端接口都需要对会话请求再次进行权限校验! +前端的鉴权只是一个辅助功能,对于专业人员这些限制都是可以轻松绕过的, +为保证服务器安全,**无论前端是否进行了权限校验,后端接口都需要对会话请求再次进行权限校验!** diff --git a/sa-token-doc/use/login-auth.md b/sa-token-doc/use/login-auth.md index bc800048..18be865f 100644 --- a/sa-token-doc/use/login-auth.md +++ b/sa-token-doc/use/login-auth.md @@ -3,7 +3,7 @@ --- -### 设计思路 +### 1、设计思路 对于一些登录之后才能访问的接口(例如:查询我的账号资料),我们通常的做法是增加一层接口校验: @@ -23,7 +23,7 @@ -### 登录与注销 +### 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 /** * 登录测试 diff --git a/sa-token-doc/use/route-check.md b/sa-token-doc/use/route-check.md index 9802747d..13b15458 100644 --- a/sa-token-doc/use/route-check.md +++ b/sa-token-doc/use/route-check.md @@ -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 { diff --git a/sa-token-doc/use/session.md b/sa-token-doc/use/session.md index 27e9aad7..c86e69ce 100644 --- a/sa-token-doc/use/session.md +++ b/sa-token-doc/use/session.md @@ -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
-例如以商品id作为key为每个商品分配一个Session,以便于缓存和商品相关的数据,其相关API如下: +### Custom-Session +自定义 Session 指的是以一个`特定的值`作为 SessionId 来分配的`Session`, 借助自定义Session,你可以为系统中的任意元素分配相应的session
+例如以商品 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, ); // 取值 (指定转换类型, 并指定值为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) {