优化文档

This commit is contained in:
click33 2021-07-21 14:39:50 +08:00
parent 23a9fb3447
commit cbc28d392b
6 changed files with 87 additions and 27 deletions

View File

@ -30,14 +30,14 @@ Sa-Token是一个轻量级Java权限认证框架主要解决登录认证
框架集成简单、开箱即用、API设计清爽通过Sa-Token你将以一种极其简单的方式实现系统的权限认证部分
- **登录证** —— 单端登录、多端登录、同端互斥登录、七天内免登录
- **权限证** —— 权限认证、角色认证、会话二级认证
- **登录证** —— 单端登录、多端登录、同端互斥登录、七天内免登录
- **权限证** —— 权限认证、角色认证、会话二级认证
- **Session会话** —— 全端共享Session、单端独享Session、自定义Session
- **踢人下线** —— 根据账号id踢人下线、根据Token值踢人下线
- **账号封禁** —— 指定天数封禁、永久封禁、设定解封时间
- **持久层扩展** —— 可集成Redis、Memcached等专业缓存中间件重启数据不丢失
- **分布式会话** —— 提供jwt集成、共享数据中心两种分布式会话方案
- **微服务网关鉴权** —— 适配Gateway、Soul、Zuul等常见网关的路由拦截认证
- **微服务网关鉴权** —— 适配Gateway、ShenYu、Zuul等常见网关的路由拦截认证
- **单点登录** —— 内置三种单点登录模式无论是否跨域、是否共享Redis都可以搞定
- **二级认证** —— 在已登录的基础上再次认证,保证安全性
- **独立Redis** —— 将权限缓存与业务缓存分离

View File

@ -1,4 +1,4 @@
# 集成
# 集成 Sa-Token
------
@ -73,7 +73,7 @@ implementation 'cn.dev33:sa-token-core:${sa.top.version}'
```
<!-- tabs:end -->
JDK版本`v1.8+`
JDK版本`v1.8+`SpringBoot`建议2.0以上`
## 获取源码

View File

@ -9,7 +9,7 @@
在IDE中新建一个SpringBoot项目例如`sa-token-demo-springboot`不会的同学请自行百度或者参考github示例
### 2、设置依赖
### 2、添加依赖
`pom.xml` 中添加依赖:
``` xml

View File

@ -1,17 +1,19 @@
# Spring WebFlux 集成 Sa-Token 示例
WebFlux基于Reactor响应式模型开发有着与标准ServletAPI完全不同的底层架构因此要适配WebFlux, 必须提供与Reactor相关的整合实现
本篇将以WebFlux为例展示Sa-Token与Reactor响应式模型web框架相整合的示例, **你可以用同样方式去对接其它Reactor模型Web框架**(Netty、ShenYu、Gateway等)
**Reactor** 是一种非阻塞的响应式模型,本篇将 **WebFlux** 以为例,展示 Sa-Token 与 Reactor 响应式模型架相整合的示例
**你可以用同样方式去对接其它Reactor模型框架Netty、ShenYu、SpringCloud Gateway等**
整合示例在官方仓库的`/sa-token-demo/sa-token-demo-webflux`文件夹下,如遇到难点可结合源码进行测试学习
!> WebFlux常用于微服务网关架构中如果您的应用基于单体架构且非 Reactor 模型,可以先跳过本章
---
### 1、创建项目
在IDE中新建一个SpringBoot项目例如`sa-token-demo-webflux`不会的同学请自行百度或者参考github示例
### 2、设置依赖
### 2、添加依赖
`pom.xml` 中添加依赖:
``` xml
@ -24,7 +26,7 @@ WebFlux基于Reactor响应式模型开发有着与标准ServletAPI完全不
```
### 4、创建启动类
### 3、创建启动类
在项目中新建包 `com.pj` ,在此包内新建主类 `SaTokenDemoApplication.java`,输入以下代码:
``` java
@ -37,7 +39,7 @@ public class SaTokenDemoApplication {
}
```
### 5、创建全局过滤器
### 4、创建全局过滤器
新建`SaTokenConfigure.java`注册Sa-Token的全局过滤器
``` java
/**
@ -72,7 +74,7 @@ public class SaTokenConfigure {
?> 你只需要按照此格式复制代码即可,有关过滤器的详细用法,会在之后的章节详细介绍
### 6、创建测试Controller
### 5、创建测试Controller
``` java
@RestController
@RequestMapping("/user/")
@ -98,7 +100,7 @@ public class UserController {
}
```
### 7、运行
### 6、运行
启动代码,从浏览器依次访问上述测试接口:
![运行结果](https://oss.dev33.cn/sa-token/doc/test-do-login.png)

View File

@ -16,7 +16,7 @@
### 获取当前账号权限码集合
因为每个项目的需求不同,其权限设计也千变万化,因此【获取当前账号权限码集合】这一操作不可能内置到框架中,
所以`Sa-Token`将此操作以接口的方式暴露给你,以方便的你根据自己的业务逻辑进行重写
所以 Sa-Token 将此操作以接口的方式暴露给你,以方便的你根据自己的业务逻辑进行重写
你需要做的就是新建一个类,实现`StpInterface`接口,例如以下代码:
@ -156,5 +156,62 @@ 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 -> 权限列表]` 一条缓存即可
一言以蔽之:权限的缓存模型需要跟着权限模型走,角色缓存亦然

View File

@ -4,8 +4,8 @@
### 核心思想
所谓登录认证,说白了就是限制某些接口只有登录后才能访问(如:查询我的账号资料) <br>
那么判断一个会话是否登录的依据是什么?当然是登录成功后框架给你做个标记!然后在需要鉴权的接口里检查此标记,有标记者视为已登录,无标记者视为未登录!
所谓登录认证,说白了就是限制某些API接口必须登录后才能访问:查询我的账号资料) <br>
那么如何判断一个会话是否登录?框架会在登录成功后给你做个标记,每次登录认证时校验这个标记,有标记者视为已登录,无标记者视为未登录!
### 登录与注销
@ -26,33 +26,34 @@ StpUtil.isLogin();
StpUtil.checkLogin()
```
扩展:`NotLoginException` 对象可通过 `getLoginType()` 方法获取具体是哪个 `StpLogic` 抛出的异常 <br>
扩展:`NotLoginException` 对象可通过 `getType()` 方法获取具体的场景值,详细参考章节:[未登录场景值](/fun/not-login-scene)
##### `NotLoginException`异常对象扩展:
1. 通过 `getLoginType()` 方法获取具体是哪个 `StpLogic` 抛出的异常 <br>
2. 通过 `getType()` 方法获取具体的场景值,详细参考章节:[未登录场景值](/fun/not-login-scene)
### 会话查询
``` java
// 获取当前会话登录id, 如果未登录,则抛出异常:`NotLoginException`
// 获取当前会话账号id, 如果未登录,则抛出异常:`NotLoginException`
StpUtil.getLoginId();
// 类似查询API还有
StpUtil.getLoginIdAsString(); // 获取当前会话登录id, 并转化为`String`类型
StpUtil.getLoginIdAsInt(); // 获取当前会话登录id, 并转化为`int`类型
StpUtil.getLoginIdAsLong(); // 获取当前会话登录id, 并转化为`long`类型
StpUtil.getLoginIdAsString(); // 获取当前会话账号id, 并转化为`String`类型
StpUtil.getLoginIdAsInt(); // 获取当前会话账号id, 并转化为`int`类型
StpUtil.getLoginIdAsLong(); // 获取当前会话账号id, 并转化为`long`类型
// ---------- 指定未登录情形下返回的默认值 ----------
// 获取当前会话登录id, 如果未登录则返回null
// 获取当前会话账号id, 如果未登录则返回null
StpUtil.getLoginIdDefaultNull();
// 获取当前会话登录id, 如果未登录,则返回默认值 `defaultValue`可以为任意类型)
// 获取当前会话账号id, 如果未登录,则返回默认值 `defaultValue`可以为任意类型)
StpUtil.getLoginId(T defaultValue);
```
### 其它API
``` java
// 获取指定token对应的登录id如果未登录则返回 null
// 获取指定token对应的账号id如果未登录则返回 null
StpUtil.getLoginIdByToken(String tokenValue);
// 获取当前`StpLogic`的token名称
@ -65,6 +66,6 @@ StpUtil.getTokenValue();
StpUtil.getTokenInfo();
```
?> 有关TokenInfo参数详解请参考[参考:TokenInfo参数详解](/fun/token-info)
有关`TokenInfo`参数详解,请参考:[TokenInfo参数详解](/fun/token-info)