mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-10-27 02:59:02 +08:00
v1.26.1 beta
This commit is contained in:
@@ -77,6 +77,7 @@
|
||||
- [Session模型详解](/fun/session-model)
|
||||
- [TokenInfo参数详解](/fun/token-info)
|
||||
- [解决反向代理 uri 丢失的问题](/fun/curr-domain)
|
||||
- [参考:把权限放在缓存里](/fun/jur-cache)
|
||||
- [解决跨域问题](/fun/cors-filter)
|
||||
- [框架源码所有技术栈](/fun/tech-stack)
|
||||
- [为Sa-Token贡献代码](/fun/git-pr)
|
||||
|
||||
52
sa-token-doc/doc/fun/jur-cache.md
Normal file
52
sa-token-doc/doc/fun/jur-cache.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# 参考:将权限数据放在缓存里
|
||||
前面我们讲解了如何通过`StpInterface`接口注入权限数据,框架默认是不提供缓存能力的,如果你想减小数据库的访问压力,则需要将权限数据放到缓存中
|
||||
|
||||
---
|
||||
|
||||
参考示例:
|
||||
``` java
|
||||
/**
|
||||
* 返回一个账号所拥有的权限码集合
|
||||
*/
|
||||
@Override
|
||||
public List<String> getPermissionList(Object loginId, String loginType) {
|
||||
|
||||
// 1. 获取这个账号所属角色id
|
||||
long roleId = StpUtil.getSessionByLoginId(loginId).get("Role_Id", () -> {
|
||||
return ...; // 从数据库查询这个账号所属的角色id
|
||||
});
|
||||
|
||||
// 2. 获取这个角色id拥有的权限列表
|
||||
SaSession roleSession = SaSessionCustomUtil.getSessionById("role-" + roleId);
|
||||
List<String> list = roleSession.get("Permission_List", () -> {
|
||||
return ...; // 从数据库查询这个角色id拥有的权限列表
|
||||
});
|
||||
|
||||
// 3. 返回
|
||||
return list;
|
||||
}
|
||||
```
|
||||
|
||||
##### 疑问:为什么不直接缓存 `[账号id->权限列表]`的关系,而是 `[账号id -> 角色id -> 权限列表]`?
|
||||
|
||||
<!-- ``` java
|
||||
// 在一个账号登录时写入其权限数据
|
||||
RedisUtil.setValue("账号id", <权限列表>);
|
||||
|
||||
// 然后在`StpInterface`接口中,如下方式获取
|
||||
List<String> list = RedisUtil.getValue("账号id");
|
||||
``` -->
|
||||
|
||||
答:`[账号id->权限列表]`的缓存方式虽然更加直接粗暴,却有一个严重的问题:
|
||||
|
||||
- 通常我们系统的权限架构是RBAC模型:权限与用户没有直接的关系,而是:用户拥有指定的角色,角色再拥有指定的权限
|
||||
- 而这种'拥有关系'是动态的,是可以随时修改的,一旦我们修改了它们的对应关系,便要同步修改或清除对应的缓存数据
|
||||
|
||||
现在假设如下业务场景:我们系统中有十万个账号属于同一个角色,当我们变动这个角色的权限时,难道我们要同时清除这十万个账号的缓存信息吗?
|
||||
这显然是一个不合理的操作,同一时间缓存大量清除容易引起Redis的缓存雪崩
|
||||
|
||||
而当我们采用 `[账号id -> 角色id -> 权限列表]` 的缓存模型时,则只需要清除或修改 `[角色id -> 权限列表]` 一条缓存即可
|
||||
|
||||
一言以蔽之:权限的缓存模型需要跟着权限模型走,角色缓存亦然
|
||||
|
||||
|
||||
@@ -144,7 +144,9 @@
|
||||
<script src="https://unpkg.zhimg.com/docsify@4.9.4/lib/docsify.min.js"></script>
|
||||
<script src="https://unpkg.zhimg.com/docsify-copy-code@2.1.0/dist/docsify-copy-code.min.js"></script>
|
||||
<script src="https://unpkg.zhimg.com/prismjs@1.20.0/components/prism-java.min.js"></script>
|
||||
<!-- 搜索框 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
|
||||
<!-- 多 tab 切换 -->
|
||||
<script src="https://unpkg.zhimg.com/docsify-tabs@1.4.4"></script>
|
||||
<!-- img点击放大 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script>
|
||||
|
||||
@@ -84,7 +84,7 @@ public class UserController {
|
||||
|
||||
// 查询登录状态,浏览器访问: http://localhost:8081/user/isLogin
|
||||
@RequestMapping("isLogin")
|
||||
public String isLogin(String username, String password) {
|
||||
public String isLogin() {
|
||||
return "当前会话是否登录:" + StpUtil.isLogin();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ Sa-token默认将数据保存在内存中,此模式读写速度最快,且避
|
||||
|
||||
---
|
||||
|
||||
### 方式A. 使用jdk默认序列化方式 (Sa-Token 整合 Redis)
|
||||
### 方式1. Sa-Token 整合 Redis (使用jdk默认序列化方式)
|
||||
``` xml
|
||||
<!-- Sa-Token 整合 Redis (使用jdk默认序列化方式) -->
|
||||
<dependency>
|
||||
@@ -25,7 +25,7 @@ Sa-token默认将数据保存在内存中,此模式读写速度最快,且避
|
||||
优点:兼容性好,缺点:Session序列化后基本不可读,对开发者来讲等同于乱码
|
||||
|
||||
|
||||
### 方式B. 使用jackson序列化方式(Sa-Token 整合 Redis)
|
||||
### 方式2. Sa-Token 整合 Redis(使用jackson序列化方式)
|
||||
``` xml
|
||||
<!-- Sa-Token 整合 Redis (使用jackson序列化方式) -->
|
||||
<dependency>
|
||||
@@ -64,8 +64,8 @@ spring:
|
||||
port: 6379
|
||||
# Redis服务器连接密码(默认为空)
|
||||
# password:
|
||||
# 连接超时时间(毫秒)
|
||||
timeout: 1000ms
|
||||
# 连接超时时间
|
||||
timeout: 10s
|
||||
lettuce:
|
||||
pool:
|
||||
# 连接池最大连接数
|
||||
|
||||
@@ -163,53 +163,3 @@ StpUtil.hasPermission("index.html"); // false
|
||||
前端的鉴权只是一个辅助功能,对于专业人员这些限制都是可以轻松绕过的,为保证服务器安全,无论前端是否进行了权限校验,后端接口都需要对会话请求再次进行权限校验!
|
||||
|
||||
|
||||
### 将权限数据放在缓存里
|
||||
前面我们讲解了如何通过`StpInterface`接口注入权限数据,框架默认是不提供缓存能力的,如果你想减小数据库的访问压力,则需要将权限数据放到缓存中
|
||||
|
||||
参考示例:
|
||||
``` java
|
||||
/**
|
||||
* 返回一个账号所拥有的权限码集合
|
||||
*/
|
||||
@Override
|
||||
public List<String> getPermissionList(Object loginId, String loginType) {
|
||||
|
||||
// 1. 获取这个账号所属角色id
|
||||
long roleId = StpUtil.getSessionByLoginId(loginId).get("Role_Id", () -> {
|
||||
return ...; // 从数据库查询这个账号所属的角色id
|
||||
});
|
||||
|
||||
// 2. 获取这个角色id拥有的权限列表
|
||||
SaSession roleSession = SaSessionCustomUtil.getSessionById("role-" + roleId);
|
||||
List<String> list = roleSession.get("Permission_List", () -> {
|
||||
return ...; // 从数据库查询这个角色id拥有的权限列表
|
||||
});
|
||||
|
||||
// 3. 返回
|
||||
return list;
|
||||
}
|
||||
```
|
||||
|
||||
##### 疑问:为什么不直接缓存 `[账号id->权限列表]`的关系,而是 `[账号id -> 角色id -> 权限列表]`?
|
||||
|
||||
<!-- ``` java
|
||||
// 在一个账号登录时写入其权限数据
|
||||
RedisUtil.setValue("账号id", <权限列表>);
|
||||
|
||||
// 然后在`StpInterface`接口中,如下方式获取
|
||||
List<String> list = RedisUtil.getValue("账号id");
|
||||
``` -->
|
||||
|
||||
答:`[账号id->权限列表]`的缓存方式虽然更加直接粗暴,却有一个严重的问题:
|
||||
|
||||
- 通常我们系统的权限架构是RBAC模型:权限与用户没有直接的关系,而是:用户拥有指定的角色,角色再拥有指定的权限
|
||||
- 而这种'拥有关系'是动态的,是可以随时修改的,一旦我们修改了它们的对应关系,便要同步修改或清除对应的缓存数据
|
||||
|
||||
现在假设如下业务场景:我们系统中有十万个账号属于同一个角色,当我们变动这个角色的权限时,难道我们要同时清除这十万个账号的缓存信息吗?
|
||||
这显然是一个不合理的操作,同一时间缓存大量清除容易引起Redis的缓存雪崩
|
||||
|
||||
而当我们采用 `[账号id -> 角色id -> 权限列表]` 的缓存模型时,则只需要清除或修改 `[角色id -> 权限列表]` 一条缓存即可
|
||||
|
||||
一言以蔽之:权限的缓存模型需要跟着权限模型走,角色缓存亦然
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user