优化文档

This commit is contained in:
click33
2021-07-22 20:36:46 +08:00
parent 95beaee6ee
commit ef1507e5b7
13 changed files with 161 additions and 51 deletions

View File

@@ -0,0 +1,18 @@
package com.pj.satoken;
import org.springframework.stereotype.Component;
import cn.dev33.satoken.action.SaTokenActionDefaultImpl;
import cn.dev33.satoken.util.SaFoxUtil;
/**
* 继承Sa-Token行为Bean默认实现, 重写部分逻辑
*/
@Component
public class MySaTokenAction extends SaTokenActionDefaultImpl {
// 重写token生成策略
@Override
public String createToken(Object loginId, String loginType) {
return SaFoxUtil.getRandomString(60); // 随机60位字符串
}
}

View File

@@ -16,17 +16,19 @@
- [框架配置](/use/config)
- **深入**
- [持久层扩展集成Redis](/use/dao-extend)
- [无Cookie模式前后台分离](/use/not-cookie)
- [花式token](/use/token-style)
- [Token前缀](/use/token-prefix)
- [记住我模式](/use/remember-me)
- [模拟他人 & 身份切换](/use/mock-person)
- [同端互斥登录](/use/mutex-login)
- [二级认证](/use/safe-auth)
- [密码加密](/use/password-secure)
- [会话治理](/use/search-session)
- [全局侦听器](/use/global-listener)
<!-- - [持久层扩展集成Redis](/use/dao-extend) -->
- [集成Redis](/up/integ-redis)
<!-- - [无Cookie模式前后台分离](/use/not-cookie) -->
- [前后台分离](/up/not-cookie)
- [自定义Token风格](/up/token-style)
- [自定义Token前缀](/up/token-prefix)
- [记住我模式](/up/remember-me)
- [模拟他人 & 身份切换](/up/mock-person)
- [同端互斥登录](/up/mutex-login)
- [二级认证](/up/safe-auth)
- [密码加密](/up/password-secure)
- [会话治理](/up/search-session)
- [全局侦听器](/up/global-listener)
- **进阶**
- [全局过滤器](/use/global-filter)

View File

@@ -11,7 +11,7 @@
### 自定义侦听器实现
新建`MySaTokenListener.java`,继承`SaTokenListener`接口, 并添加上注解`@Component`,保证此类被`SpringBoot`扫描到
新建`MySaTokenListener.java`,继承`SaTokenListener`接口并添加上注解`@Component`,保证此类被`SpringBoot`扫描到
``` java
/**
* 自定义侦听器的实现

View File

@@ -0,0 +1,90 @@
# Sa-Token 集成 Redis
---
Sa-token默认将数据保存在内存中此模式读写速度最快且避免了序列化与反序列化带来的性能消耗但是此模式也有一些缺点比如
1. 重启后数据会丢失
2. 无法在分布式环境中共享数据
为此Sa-Token提供了扩展接口你可以轻松将会话数据存储在 `Redis``Memcached`等专业的缓存中间件中,
做到重启数据不丢失,而且保证分布式环境下多节点的会话一致性
以下是官方提供的Redis集成包
---
### 1. Sa-Token 整合 Redis 使用jdk默认序列化方式
``` xml
<!-- Sa-Token 整合 Redis 使用jdk默认序列化方式 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis</artifactId>
<version>${sa.top.version}</version>
</dependency>
```
优点兼容性好缺点Session序列化后基本不可读对开发者来讲等同于乱码
### 2. Sa-Token 整合 Redis使用jackson序列化方式
``` xml
<!-- Sa-Token 整合 Redis 使用jackson序列化方式 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis-jackson</artifactId>
<version>${sa.top.version}</version>
</dependency>
```
优点Session序列化后可读性强可灵活手动修改缺点兼容性稍差
### 集成Redis请注意
**1. 无论使用哪种序列化方式你都必须为项目提供一个Redis实例化方案例如**
``` xml
<!-- 提供redis连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
```
**2. 引入了依赖我还需要为Redis配置连接信息吗** <br>
需要只有项目初始化了正确的Redis实例`Sa-Token`才可以使用Redis进行数据持久化参考以下`yml配置`
``` java
# 端口
spring:
# redis配置
redis:
# Redis数据库索引默认为0
database: 1
# Redis服务器地址
host: 127.0.0.1
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码默认为空
# password:
# 连接超时时间(毫秒)
timeout: 1000ms
lettuce:
pool:
# 连接池最大连接数
max-active: 200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# 连接池中的最大空闲连接
max-idle: 10
# 连接池中的最小空闲连接
min-idle: 0
```
**3. 集成Redis后是我额外手动保存数据还是框架自动保存** <br>
框架自动保存。集成`Redis`只需要引入对应的`pom依赖`即可框架所有上层API保持不变
<br><br>
更多框架的集成方案正在更新中... (欢迎大家提交pr)

View File

@@ -3,7 +3,7 @@
以上介绍的api都是操作当前账号对当前账号进行各种鉴权操作你可能会问我能不能对别的账号进行一些操作<br>
比如:查看账号`10001`有无某个权限码、获取id账号为`10002`的用户`User-Session`,等等...
比如查看账号10001有无某个权限码、获取 账号id=10002 的 `User-Session`,等等...
Sa-Token在api设计时充分考虑了这一点暴露出多个api进行此类操作
@@ -46,7 +46,7 @@ StpUtil.getLoginId();
StpUtil.endSwitch();
```
你还可以: 直接在一个代码段里方法内临时切换身份为指定loginId (此方式无需手动调用`StpUtil.endSwitch()`关闭身份切换)
你还可以: 直接在一个代码段里方法内临时切换身份为指定loginId此方式无需手动调用`StpUtil.endSwitch()`关闭身份切换
``` java
System.out.println("------- [身份临时切换]调用开始...");
StpUtil.switchTo(10044, () -> {

View File

@@ -7,7 +7,7 @@
## 具体API
`Sa-Token`中如何做到同端互斥登录? <br/>
Sa-Token 中如何做到同端互斥登录? <br/>
首先在配置文件中,将 `isConcurrent` 配置为false然后调用登录等相关接口时声明设备标识即可
@@ -16,7 +16,7 @@
// 指定`账号id``设备标识`进行登录
StpUtil.login(10001, "PC");
```
调用此方法登录后,同设备的会被顶下线(不同设备不受影响),再次访问系统时会抛出 `NotLoginException` 异常,场景值=`-4`
调用此方法登录后,同设备的会被顶下线不同设备不受影响,再次访问系统时会抛出 `NotLoginException` 异常,场景值=`-4`
#### 指定设备标识强制注销
@@ -34,7 +34,7 @@ StpUtil.getLoginDevice();
```
#### id反查token
#### Id 反查 Token
``` java
// 获取指定loginId指定设备端的tokenValue
StpUtil.getTokenValueByLoginId(10001, "APP");

View File

@@ -1,16 +1,16 @@
# 无Cookie模式
# 前后台分离(无Cookie模式
---
### 何为无Cookie模式?
无Cookie特指不支持Cookie功能的终端通俗来讲就是我们常说的 —— **前后台分离模式**
常规PC端鉴权方法一般由`Cookie模式`完成,而`Cookie`有两个特性:
常规PC端鉴权方法一般由`Cookie模式`完成,而 Cookie 有两个特性:
1. 可由后端控制写入
2. 每次请求自动提交
这就使得我们在前端代码中,无需任何特殊操作,就能完成鉴权的全部流程(因为整个流程都是后端控制完成的)<br/>
而在app、小程序等前后台分离场景中一般是没有`Cookie`这一功能的,此时大多数人都会一脸懵逼,咋进行鉴权啊?
而在app、小程序等前后台分离场景中一般是没有 Cookie 这一功能的,此时大多数人都会一脸懵逼,咋进行鉴权啊?
见招拆招,其实答案很简单:
- 不能后端控制写入了,就前端自己写入(难点在**后端如何将token传递到前端**
@@ -20,14 +20,14 @@
### 1、后端将 token 返回到前端
1. 首先调用 `StpUtil.login(Object loginId)` 进行登录
1. 首先调用 `StpUtil.login(id)` 进行登录
2. 调用 `StpUtil.getTokenInfo()` 返回当前会话的token详细参数
- 此方法返回一个对象,其有两个关键属性:`tokenName``tokenValue``token`的名称和`token`的值)
- 此方法返回一个对象,其有两个关键属性:`tokenName``tokenValue`token 的名称和 token 的值)
- 将此对象传递到前台,让前端人员将这两个值保存到本地
### 2、前端将 token 提交到后端
1. 无论是app还是小程序其传递方式都大同小异
2. 那就是,将`token`塞到请求`header`里 ,格式为:`{tokenName: tokenValue}`
2. 那就是,将 token 塞到请求`header`里 ,格式为:`{tokenName: tokenValue}`
3. 以经典跨端框架 [uni-app](https://uniapp.dcloud.io/) 为例:
**方式1简单粗暴**
@@ -60,7 +60,7 @@ uni.setStorageSync('tokenValue', tokenValue);
var tokenName = uni.getStorageSync('tokenName'); // 从本地缓存读取tokenName值
var tokenValue = uni.getStorageSync('tokenValue'); // 从本地缓存读取tokenValue值
var header = {
"content-type": "application/x-www-form-urlencoded" // 防止后台拿不到参数
"content-type": "application/x-www-form-urlencoded"
};
if (tokenName != undefined && tokenName != '') {
header[tokenName] = tokenValue;
@@ -76,14 +76,14 @@ uni.request({
});
```
4. 只要按照如此方法将`token`值传递到后端,`Sa-Token`就能像传统PC端一样自动读取到`token`值,进行鉴权
4. 只要按照如此方法将`token`值传递到后端Sa-Token 就能像传统PC端一样自动读取到 token 值,进行鉴权
5. 你可能会有疑问,难道我每个`ajax`都要写这么一坨?岂不是麻烦死了
- 你当然不能每个`ajax`都写这么一坨,因为这种重复代码都是要封装在一个函数里统一调用的
- 你当然不能每个 ajax 都写这么一坨,因为这种重复代码都是要封装在一个函数里统一调用的
### 其它解决方案?
如果你对`Cookie`非常了解,那你就会明白,所谓`Cookie`,本质上就是一个特殊的`header`参数而已 <br>
而既然它只是一个`header`参数,我们就能手动模拟实现它,从而完成鉴权操作
如果你对 Cookie 非常了解,那你就会明白,所谓 Cookie ,本质上就是一个特殊的`header`参数而已 <br>
而既然它只是一个 header 参数,我们就能手动模拟实现它,从而完成鉴权操作
这其实是对`无Cookie模式`的另一种解决方案,有兴趣的同学可以百度了解一下,在此暂不赘述

View File

@@ -1,7 +1,7 @@
# [记住我]模式
# [记住我] 模式
---
图所示,一般网站的登录界面都会有一个 [ 记住我 ] 按钮,当你勾选它后,即时你关闭浏览器再次打开网站,也依然会处于登录状态,无须重复验证密码
如图所示,一般网站的登录界面都会有一个 **`[记住我]`** 按钮,当你勾选它后,即时你关闭浏览器再次打开网站,也依然会处于登录状态,无须重复验证密码
![../static/login-view.png](../static/login-view.png)
@@ -26,8 +26,8 @@ Cookie作为浏览器提供的默认会话跟踪机制其生命周期有两
- 永久Cookie有效期为一个具体的时间在时间未到期之前即使用户关闭了浏览器Cookie也不会消失
利用Cookie的此特性我们便可以轻松实现 [记住我] 模式:
- 勾选[记住我]按钮时:调用`StpUtil.login(10001, true)`,在浏览器写入一个`永久Cookie`储存token此时用户即使重启浏览器token依然有效
- 不勾选[记住我]按钮时:调用`StpUtil.login(10001, false)`,在浏览器写入一个`临时Cookie`储存token此时用户在重启浏览器后token便会消失导致会话失效
- 勾选 [记住我] 按钮时:调用`StpUtil.login(10001, true)`,在浏览器写入一个`永久Cookie`储存 Token此时用户即使重启浏览器 Token 依然有效
- 不勾选 [记住我] 按钮时:调用`StpUtil.login(10001, false)`,在浏览器写入一个`临时Cookie`储存 Token此时用户在重启浏览器后 Token 便会消失,导致会话失效
### 前后台分离模式下如何实现[记住我]?

View File

@@ -1,4 +1,4 @@
# Token前缀
# 自定义 Token 前缀
### 需求场景
@@ -16,15 +16,15 @@
``` java
sa-token:
# token前缀
tokenPrefix: Bearer
token-prefix: Bearer
```
此时 Sa-Token 便可在读取token时裁剪掉 `Bearer`,成功获取`xxxx-xxxx-xxxx-xxxx`
此时 Sa-Token 便可在读取 Token 时裁剪掉 `Bearer`,成功获取`xxxx-xxxx-xxxx-xxxx`
### 注意点
1. `token前缀``token值` 之间必须有一个空格
2. 一旦配置了`token前缀`则前端提交token时必须带有前缀否则会导致框架无法读取token
3. 由于`Cookie`中无法存储空格字符也就意味配置token前缀后`Cookie`鉴权方式将会失效此时只能将token提交到`header`里进行传输
1. Token前缀 Token值 之间必须有一个空格
2. 一旦配置了 Token前缀则前端提交token时必须带有前缀否则会导致框架无法读取token
3. 由于`Cookie`中无法存储空格字符也就意味配置token前缀后Cookie鉴权方式将会失效此时只能将token提交到`header`里进行传输

View File

@@ -1,13 +1,13 @@
# 花式token
# 自定义 Token 风格
本篇介绍token生成的各种风格以及自定义token生成策略
本篇介绍token生成的各种风格以及自定义token生成策略
---
## 内置风格
Sa-Token默认的token生成策略是uuid风格, 其模样类似于:`623368f0-ae5e-4475-a53f-93e4225f16ae`<br>
Sa-Token默认的token生成策略是uuid风格其模样类似于:`623368f0-ae5e-4475-a53f-93e4225f16ae`<br>
如果你对这种风格不太感冒还可以将token生成设置为其他风格
怎么设置呢只需要在yml配置文件里设置 `sa-token.token-style=风格类型` 即可,其有多种取值:
@@ -56,7 +56,7 @@ public class MySaTokenAction extends SaTokenActionDefaultImpl {
// 重写token生成策略
@Override
public String createToken(Object loginId, String loginType) {
return SaTokenInsideUtil.getRandomString(60); // 随机60位字符串
return SaFoxUtil.getRandomString(60); // 随机60位字符串
}
}
```
@@ -68,20 +68,20 @@ gfuPSwZsnUhwgz08GTCH4wOgasWtc3odP4HLwXJ7NDGOximTvT4OlW19zeLH
## 以雪花算法生成token
在此再举一个例子,以`自定义token生成策略`的方式集成`雪花算法`来生成token
<!-- ## 以雪花算法生成token
在此再举一个例子,以`自定义token生成策略`的方式集成`雪花算法`来生成token -->
1、首先我们需要找一个合适的类库帮助我们生成雪花算法唯一id在此推荐 [Hutool](https://hutool.cn/docs/#/) ,在`pom.xml`里添加依赖:
<!-- 1、首先我们需要找一个合适的类库帮助我们生成雪花算法唯一id在此推荐 [Hutool](https://hutool.cn/docs/#/) ,在`pom.xml`里添加依赖:
``` xml
<!-- Hutool 一个小而全的Java工具类库 -->
Hutool 一个小而全的Java工具类库
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.4</version>
</dependency>
```
``` -->
2、同上我们需要新建文件`MySaTokenAction.java`,继承`SaTokenActionDefaultImpl`默认实现类, 并添加上注解`@Component`,保证此类被`springboot`扫描到
<!-- 2、同上我们需要新建文件`MySaTokenAction.java`,继承`SaTokenActionDefaultImpl`默认实现类, 并添加上注解`@Component`,保证此类被`springboot`扫描到
``` java
package com.pj.satoken;
@@ -100,9 +100,9 @@ public class MySaTokenAction extends SaTokenActionDefaultImpl {
return IdUtil.getSnowflake(1, 1).nextIdStr(); // 以雪花算法生成token
}
}
```
``` -->
3、再次调用 `StpUtil.login(10001)`方法进行登录观察其生成的token样式:
<!-- 3、再次调用 `StpUtil.login(10001)`方法进行登录观察其生成的token样式:
``` html
1339604338175250432
```
``` -->