mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-10-20 18:47:25 +08:00
v1.8.0更新
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
<p align="center">
|
||||
<img alt="logo" src="https://gitee.com/sz6/sa-token/raw/master/sa-token-doc/doc/logo.png" width="150" height="150" style="margin-bottom: 10px;">
|
||||
</p>
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">sa-token v1.7.0</h1>
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">sa-token v1.8.0</h1>
|
||||
<h4 align="center">一个JavaWeb轻量级权限认证框架,功能全面,上手简单</h4>
|
||||
<h4 align="center">
|
||||
<a href="https://gitee.com/sz6/sa-token/stargazers"><img src="https://gitee.com/sz6/sa-token/badge/star.svg"></a>
|
||||
<a href="https://github.com/click33/sa-token"><img src="https://img.shields.io/badge/sa--token-v1.7.0-2B9939"></a>
|
||||
<a href="https://github.com/click33/sa-token"><img src="https://img.shields.io/badge/sa--token-v1.8.0-2B9939"></a>
|
||||
<a href="https://github.com/click33/sa-token/stargazers"><img src="https://img.shields.io/github/stars/click33/sa-token"></a>
|
||||
<a href="https://github.com/click33/sa-token/watchers"><img src="https://img.shields.io/github/watchers/click33/sa-token"></a>
|
||||
<a href="https://github.com/click33/sa-token/network/members"><img src="https://img.shields.io/github/forks/click33/sa-token"></a>
|
||||
@@ -17,28 +17,29 @@
|
||||
|
||||
|
||||
## 😘 在线资料
|
||||
- ##### [官网首页:http://sa-token.dev33.cn/](http://sa-token.dev33.cn/)
|
||||
- ##### [在线文档:http://sa-token.dev33.cn/doc/index.html](http://sa-token.dev33.cn/doc/index.html)
|
||||
- ##### [需求提交:我们深知一个优秀的项目需要海纳百川,点我在线提交需求](http://sa-app.dev33.cn/wall.html?name=sa-token)
|
||||
- ##### [开源不易,求鼓励,点个star吧](https://github.com/click33/sa-token)
|
||||
|
||||
- [官网首页:http://sa-token.dev33.cn/](http://sa-token.dev33.cn/)
|
||||
|
||||
- [在线文档:http://sa-token.dev33.cn/doc/index.html](http://sa-token.dev33.cn/doc/index.html)
|
||||
|
||||
- [需求提交:我们深知一个优秀的项目需要海纳百川,点我在线提交需求](http://sa-app.dev33.cn/wall.html?name=sa-token)
|
||||
|
||||
- [开源不易,求鼓励,点个star吧](https://github.com/click33/sa-token)
|
||||
|
||||
|
||||
## ⭐ sa-token是什么?
|
||||
- **sa-token是一个JavaWeb轻量级权限认证框架,其API调用非常简单,有多简单呢?以登录验证为例,你只需要:**
|
||||
**sa-token是一个JavaWeb轻量级权限认证框架,其API调用非常简单,有多简单呢?以登录验证为例,你只需要:**
|
||||
|
||||
``` java
|
||||
// 在登录时写入当前会话的账号id
|
||||
StpUtil.setLoginId(10001);
|
||||
StpUtil.setLoginId(10001);
|
||||
|
||||
// 然后在任意需要校验登录处调用以下API --- 如果当前会话未登录,这句代码会抛出 `NotLoginException`异常
|
||||
StpUtil.checkLogin();
|
||||
```
|
||||
|
||||
|
||||
- **然后在任意需要验证登录权限的地方:**
|
||||
``` java
|
||||
// 检测是否登录 --- 如果当前会话未登录,下面这句代码会抛出 `NotLoginException`异常
|
||||
StpUtil.checkLogin();
|
||||
```
|
||||
|
||||
|
||||
- **没有复杂的封装!不要任何的配置!先写入,后鉴权!只需这两行简单的调用,即可轻松完成系统登录鉴权!**
|
||||
**没有复杂的封装!不要任何的配置!只需这两行简单的调用,即可轻松完成系统登录鉴权!**
|
||||
|
||||
|
||||
## 🔥 框架设计思想
|
||||
@@ -47,20 +48,38 @@ StpUtil.checkLogin();
|
||||
- 功能强大:能涵盖的功能全部涵盖,不让你用个框架还要自己给框架打各种补丁
|
||||
|
||||
|
||||
**如果上面的示例能够证明`sa-token`的简单,那么以下API则可以证明`sa-token`的强大**
|
||||
``` java
|
||||
StpUtil.setLoginId(10001); // 标记当前会话登录的账号id
|
||||
StpUtil.getLoginId(); // 获取当前会话登录的账号id
|
||||
StpUtil.isLogin(); // 获取当前会话是否已经登录, 返回true或false
|
||||
StpUtil.logout(); // 当前会话注销登录
|
||||
StpUtil.logoutByLoginId(10001); // 让账号为10001的会话注销登录(踢人下线)
|
||||
StpUtil.hasRole("super-admin"); // 查询当前账号是否含有指定角色标识, 返回true或false
|
||||
StpUtil.hasPermission("user:add"); // 查询当前账号是否含有指定权限, 返回true或false
|
||||
StpUtil.getSession(); // 获取当前账号id的Session
|
||||
StpUtil.getSessionByLoginId(10001); // 获取账号id为10001的Session
|
||||
StpUtil.getTokenValueByLoginId(10001); // 获取账号id为10001的token令牌值
|
||||
```
|
||||
**sa-token的API众多,请恕此处无法为您逐一展示,更多示例请戳官方在线文档**
|
||||
|
||||
|
||||
|
||||
|
||||
## 💦️️ 涵盖功能
|
||||
- ⚡ **登录验证** —— 轻松登录鉴权,并提供五种细分场景值
|
||||
- ⚡ **权限验证** —— 拦截违规调用,不同角色不同授权
|
||||
- ⚡ **自定义session会话** —— 专业的数据缓存中心
|
||||
- ⚡ **踢人下线** —— 将违规用户立刻清退下线
|
||||
- ⚡ **模拟他人账号** —— 实时操作任意用户状态数据
|
||||
- ⚡ **持久层扩展** —— 可集成redis、MongoDB等专业缓存中间件
|
||||
- ⚡ **多账号认证体系** —— 比如一个商城项目的user表和admin表分开鉴权
|
||||
- ⚡ **无cookie模式** —— APP、小程序等前后台分离场景
|
||||
- ⚡ **注解式鉴权** —— 优雅的将鉴权与业务代码分离
|
||||
- ⚡ **花式token生成** —— 内置六种token风格,还可自定义token生成策略
|
||||
- ⚡ **自动续签** —— 提供两种token过期策略,灵活搭配使用,还可自动续签
|
||||
- ⚡ **组件自动注入** —— 零配置与Spring等框架集成
|
||||
- ⚡ **更多功能正在集成中...** —— 如有您有好想法或者建议,欢迎加群交流
|
||||
- **登录验证** —— 轻松登录鉴权,并提供五种细分场景值
|
||||
- **权限验证** —— 拦截违规调用,不同角色不同授权
|
||||
- **Session会话** —— 专业的数据缓存中心
|
||||
- **踢人下线** —— 将违规用户立刻清退下线
|
||||
- **模拟他人账号** —— 实时操作任意用户状态数据
|
||||
- **持久层扩展** —— 可集成redis、MongoDB等专业缓存中间件
|
||||
- **多账号认证体系** —— 比如一个商城项目的user表和admin表分开鉴权
|
||||
- **无Cookie模式** —— APP、小程序等前后台分离场景
|
||||
- **注解式鉴权** —— 优雅的将鉴权与业务代码分离
|
||||
- **花式token生成** —— 内置六种token风格,还可自定义token生成策略
|
||||
- **自动续签** —— 提供两种token过期策略,灵活搭配使用,还可自动续签
|
||||
- **组件自动注入** —— 零配置与Spring等框架集成
|
||||
- **更多功能正在集成中...** —— 如有您有好想法或者建议,欢迎加群交流
|
||||
|
||||
|
||||
## 🔨 贡献代码
|
||||
|
@@ -8,10 +8,10 @@
|
||||
- **使用**
|
||||
- [登录验证](/use/login-auth)
|
||||
- [权限验证](/use/jur-auth)
|
||||
- [session会话](/use/session)
|
||||
- [Session会话](/use/session)
|
||||
- [踢人下线](/use/kick)
|
||||
- [持久层扩展(集成redis)](/use/dao-extend)
|
||||
- [无cookie模式(前后台分离)](/use/not-cookie)
|
||||
- [持久层扩展(集成Redis)](/use/dao-extend)
|
||||
- [无Cookie模式(前后台分离)](/use/not-cookie)
|
||||
- [模拟他人](/use/mock-person)
|
||||
- [多账号验证](/use/many-account)
|
||||
- [注解式鉴权](/use/at-check)
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<meta name="description" content="Description">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta name="keywords" content="sa-token|sa-token框架|sa-token文档|sa-token在线文档|权限认证框架">
|
||||
<meta name="description" content="sa-token是一个JavaWeb权限认证框架,强大、简单、好用,登录验证、权限验证、自定义session会话、踢人下线、持久层扩展、无cookie模式、模拟他人账号、多账号体系、注解式鉴权、花式token、自动续签、Spring集成...,零配置开箱即用,覆盖所有应用场景,你所需要的功能,这里都有">
|
||||
<meta name="description" content="sa-token是一个JavaWeb权限认证框架,功能全面,上手简单,登录验证、权限验证、Session会话、踢人下线、集成Redis、前后台分离、模拟他人账号、多账号体系、注解式鉴权、花式token、自动续签、Spring集成...,零配置开箱即用,覆盖所有应用场景,你所需要的功能,这里都有">
|
||||
<link rel="stylesheet" href="https://unpkg.com/docsify@4.11.3/lib/themes/vue.css">
|
||||
<link rel="stylesheet" href="./lib/index.css">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="logo.png">
|
||||
@@ -22,6 +22,7 @@
|
||||
<nav>
|
||||
<select onchange="location.href=this.value">
|
||||
<option value="http://sa-token.dev33.cn/doc/index.html">最新版</option>
|
||||
<option value="http://sa-token.dev33.cn/v/v1.7.0/doc/index.html">v1.7.0</option>
|
||||
<option value="http://sa-token.dev33.cn/v/v1.6.0/doc/index.html">v1.6.0</option>
|
||||
<option value="http://sa-token.dev33.cn/v/v1.5.1/doc/index.html">v1.5.1</option>
|
||||
<option value="http://sa-token.dev33.cn/v/v1.4.0/doc/index.html">v1.4.0</option>
|
||||
@@ -36,7 +37,7 @@
|
||||
</div>
|
||||
<script>
|
||||
var name = '<img style="width: 50px; height: 50px; vertical-align: middle;" src="logo.png" alt="logo" /> ';
|
||||
name += '<b style="font-size: 24px; vertical-align: middle;">sa-token</b> <sub>v1.7.0</sub>'
|
||||
name += '<b style="font-size: 24px; vertical-align: middle;">sa-token</b> <sub>v1.8.0</sub>'
|
||||
window.$docsify = {
|
||||
name: name, // 名字
|
||||
repo: 'https://github.com/click33/sa-token', // github地址
|
||||
|
@@ -16,6 +16,8 @@
|
||||
/* 背景变黑 */
|
||||
.main-box [data-lang]{padding: 0px !important; border-radius: 8px; overflow: hidden;}
|
||||
.main-box [class^="lang-"]{border: 0px red solid; padding: 1.5em 1.2em;/* background-color: #282828; */ background-color: #090300; color: #FFF;}
|
||||
.main-box [data-lang]{overflow: auto;}
|
||||
/* .main-box h2{margin-top: 70px;} */
|
||||
|
||||
/* xml语言样式优化 */
|
||||
.lang-xml .token.comment{color: #CDAB53;}
|
||||
@@ -34,7 +36,8 @@
|
||||
/* js语言样式优化 */
|
||||
.main-box .lang-js{color: #01a252;}
|
||||
.lang-js .token.comment{color: #CDAB53;}
|
||||
.lang-js .token.string{color: #fded02;}
|
||||
/* .lang-js .token.string{color: #fded02;} */
|
||||
.lang-js .token.string{color: #ddd;}
|
||||
.lang-js .token.punctuation{color: #ddd;}
|
||||
|
||||
|
||||
|
@@ -1,6 +1,25 @@
|
||||
# 更新日志
|
||||
|
||||
|
||||
### 2020-12-24 @v1.8.0
|
||||
- 优化:优化源码注释
|
||||
- 修复:修复部分文档错别字
|
||||
- 修复:修复项目文件夹名称错误
|
||||
- 优化:优化文档配色,更舒服的代码展示
|
||||
- 新增:提供`sa-token`集成 `redis` 的 `spring-boot-starter` 方案 **[重要]**
|
||||
- 新增:新增集成 `redis` 时,以`jackson`作为序列化方案 **[重要]**
|
||||
- 新增:dao层默认实现增加定时清理过期数据功能 **[重要]**
|
||||
- 新增:新增`token专属session`, 更灵活的会话管理 **[重要]**
|
||||
- 新增:增加配置,指定在获取`token专属session`时是否必须登录
|
||||
- 新增:在无token时自动创建会话,完美兼容`token-session`会话模型! **[重要]**
|
||||
- 修改:权限码限定必须为String类型
|
||||
- 优化:注解验证模式由boolean属性改为枚举方式
|
||||
- 删除:`StpUtil`删除部分冗长API,保持API清爽性
|
||||
- 新增:新增角色验证 (角色验证与权限验证已完全分离) **[重要]**
|
||||
- 优化:移除`StpUtil.kickoutByLoginId()`API,由`logoutByLoginId`代替
|
||||
- 升级:开源协议修改为`Apache-2.0`
|
||||
|
||||
|
||||
### 2020-12-24 @v1.7.0
|
||||
- 优化:项目架构改为maven多模块形式,方便增加新模块 **[重要]**
|
||||
- 优化:与`springboot`的集成改为`springboot-starter`模式,无需`@SaTokenSetup`注解即可完成自动装配 **[重要]**
|
||||
@@ -33,7 +52,7 @@
|
||||
|
||||
### 2020-9-7 @v1.4.0
|
||||
- 优化:修改一些函数、变量名称,使其更符合阿里java代码规范
|
||||
- 优化:`tokenValue`的读取优先级改为:`request` > `body` > `header` > `cookie`
|
||||
- 优化:`tokenValue`的读取优先级改为:`request` > `body` > `header` > `cookie` **[重要]**
|
||||
- 新增:新增`isReadCookie`配置,决定是否从`cookie`里读取`token`信息
|
||||
- 优化:如果`isReadCookie`配置为`false`,那么在登录时也不会把`cookie`写入`cookie`
|
||||
- 新增:新增`getSessionByLoginId(Object loginId, boolean isCreate)`方法
|
||||
@@ -50,7 +69,7 @@
|
||||
|
||||
|
||||
### 2020-3-7 @v1.2.0
|
||||
- 新增:新增注解式验证,可在路由方法中使用注解进行权限验证
|
||||
- 新增:新增注解式验证,可在路由方法中使用注解进行权限验证 **[重要]**
|
||||
- 参考:[注解式验证](use/at-check)
|
||||
|
||||
|
||||
|
@@ -2,14 +2,14 @@
|
||||
|
||||
------
|
||||
|
||||
## maven依赖
|
||||
## Maven依赖
|
||||
在项目中直接通过 `pom.xml` 导入 `sa-token` 的依赖即可
|
||||
``` xml
|
||||
<!-- sa-token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot-starter</artifactId>
|
||||
<version>1.7.0</version>
|
||||
<version>1.8.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
@@ -21,11 +21,18 @@
|
||||
- github地址:[https://github.com/click33/sa-token](https://github.com/click33/sa-token)
|
||||
- gitee地址:[https://gitee.com/sz6/sa-token](https://gitee.com/sz6/sa-token)
|
||||
- 开源不易,求鼓励,给个`star`吧
|
||||
- 源码目录介绍
|
||||
- `sa-token-dev`: 源码
|
||||
- `sa-token-spring-boot-starter`: springboot插件化集成
|
||||
- `sa-token-demo-springboot`: springboot集成示例
|
||||
- `sa-token-doc`: 文档介绍
|
||||
- 源码目录介绍:
|
||||
```
|
||||
── sa-token
|
||||
├── sa-token-core // sa-token核心模块
|
||||
├── sa-token-spring-boot-starter // sa-token整合springboot快速集成
|
||||
├── sa-token-dao-redis // sa-token整合redis (使用jdk默认序列化方式)
|
||||
├── sa-token-dao-redis-jackson // sa-token整合redis (使用jackson序列化方式)
|
||||
├── sa-token-demo-springboot // sa-token示例
|
||||
├── sa-token-doc // sa-token开发文档
|
||||
├──pom.xml
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -18,7 +18,7 @@
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot-starter</artifactId>
|
||||
<version>1.7.0</version>
|
||||
<version>1.8.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
@@ -34,20 +34,14 @@ spring:
|
||||
token-name: satoken
|
||||
# token有效期,单位s 默认30天, -1代表永不过期
|
||||
timeout: 2592000
|
||||
# token临时有效期, 默认-1 代表不限制
|
||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
||||
activity-timeout: -1
|
||||
# 在多人登录同一账号时,是否共享会话 (为true时共用一个,为false时新登录挤掉旧登录)
|
||||
is-share: true
|
||||
# 是否尝试从请求体里读取token
|
||||
is-read-body: true
|
||||
# 是否尝试从header里读取token
|
||||
is-read-head: true
|
||||
# 是否尝试从cookie里读取token
|
||||
is-read-cookie: true
|
||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
||||
allow-concurrent-login: false
|
||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
||||
is-share: false
|
||||
# token风格
|
||||
token-style: uuid
|
||||
# 是否在初始化配置时打印版本字符画
|
||||
is-v: true
|
||||
```
|
||||
|
||||
> - 如果你习惯于 `application.properties` 类型的配置文件,那也很好办:
|
||||
@@ -60,7 +54,7 @@ spring:
|
||||
@SpringBootApplication
|
||||
public class SaTokenDemoApplication {
|
||||
public static void main(String[] args) throws JsonProcessingException {
|
||||
SpringApplication.run(SaTokenDemoApplication.class, args); // run-->
|
||||
SpringApplication.run(SaTokenDemoApplication.class, args);
|
||||
System.out.println("启动成功:sa-token配置如下:" + SaTokenManager.getConfig());
|
||||
}
|
||||
}
|
||||
|
@@ -2,8 +2,7 @@
|
||||
---
|
||||
|
||||
- 尽管我们可以方便的一句代码完成权限验证,但是有时候我们仍希望可以将鉴权代码与我们的业务代码分离开来
|
||||
- 怎么做?
|
||||
- `sa-token`内置两个注解,帮助你使用注解完成鉴权操作
|
||||
- 怎么做?`sa-token`内置三个注解,帮助你使用注解完成鉴权操作
|
||||
|
||||
|
||||
## 1、注册拦截器
|
||||
@@ -28,29 +27,59 @@
|
||||
#### 登录验证
|
||||
|
||||
``` java
|
||||
@SaCheckLogin // 注解式鉴权:当前会话必须登录才能通过
|
||||
// 注解式鉴权:当前会话必须登录才能通过
|
||||
@SaCheckLogin
|
||||
@RequestMapping("info")
|
||||
public String info() {
|
||||
return "查询用户信息";
|
||||
}
|
||||
```
|
||||
|
||||
#### 权限验证
|
||||
#### 角色验证
|
||||
|
||||
``` java
|
||||
@SaCheckPermission("user-add") // 注解式鉴权:当前会话必须具有指定权限才能通过
|
||||
// 注解式鉴权:当前会话必须具有指定角色标识才能通过
|
||||
@SaCheckRole("super-admin")
|
||||
@RequestMapping("add")
|
||||
public String add() {
|
||||
return "用户增加";
|
||||
}
|
||||
```
|
||||
|
||||
#### 注意事项
|
||||
#### 权限验证
|
||||
|
||||
``` java
|
||||
// 注解式鉴权:当前会话必须具有指定权限才能通过
|
||||
@SaCheckPermission("user-add")
|
||||
@RequestMapping("add")
|
||||
public String add() {
|
||||
return "用户增加";
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
以上两个注解都可以加在类上,代表为这个类所有方法进行鉴权
|
||||
|
||||
|
||||
## 3、设定校验模式
|
||||
`@SaCheckRole`与`@SaCheckPermission`注解可设置校验模式,例如:
|
||||
``` java
|
||||
// 注解式鉴权:只要具有其中一个权限即可通过校验
|
||||
@RequestMapping("atJurOr")
|
||||
@SaCheckPermission(value = {"user-add", "user-all", "user-delete"}, mode = SaMode.OR)
|
||||
public AjaxJson atJurOr() {
|
||||
return AjaxJson.getSuccessData("用户信息");
|
||||
}
|
||||
```
|
||||
|
||||
## 3、扩展
|
||||
|
||||
- mode有两种取值:
|
||||
- `SaMode.AND`, 标注一组权限,会话必须全部具有才可通过校验
|
||||
- `SaMode.OR`, 标注一组权限,会话只要具有其一即可通过校验
|
||||
|
||||
|
||||
|
||||
<!-- ## 3、扩展
|
||||
- 其实在注册拦截器时,我们也可以根据路由前缀设置不同 `StpLogic`, 从而达到不同模块不同鉴权方式的目的
|
||||
- 以下为参考示例:
|
||||
``` java
|
||||
@@ -63,7 +92,7 @@
|
||||
registry.addInterceptor(new SaCheckInterceptor(StpUserUtil.stpLogic)).addPathPatterns("/user/**");
|
||||
}
|
||||
}
|
||||
```
|
||||
``` -->
|
||||
|
||||
|
||||
|
||||
|
@@ -16,20 +16,14 @@ spring:
|
||||
token-name: satoken
|
||||
# token有效期,单位s 默认30天, -1代表永不过期
|
||||
timeout: 2592000
|
||||
# token临时有效期, 默认-1 代表不限制
|
||||
activity-timeout: -1
|
||||
# 在多人登录同一账号时,是否共享会话 (为true时共用一个,为false时新登录挤掉旧登录)
|
||||
is-share: true
|
||||
# 是否尝试从请求体里读取token
|
||||
is-read-body: true
|
||||
# 是否尝试从header里读取token
|
||||
is-read-head: true
|
||||
# 是否尝试从cookie里读取token
|
||||
is-read-cookie: true
|
||||
# token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
||||
activity-timeout: -1
|
||||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
||||
allow-concurrent-login: false
|
||||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
||||
is-share: false
|
||||
# token风格
|
||||
token-style: uuid
|
||||
# 是否在初始化配置时打印版本字符画
|
||||
is-v: true
|
||||
```
|
||||
|
||||
- 如果你习惯于 `application.properties` 类型的配置文件,那也很好办:
|
||||
@@ -44,20 +38,17 @@ spring:
|
||||
@Configuration
|
||||
public class MySaTokenConfig {
|
||||
|
||||
// 获取配置Bean (以代码的方式配置sa-token)
|
||||
// 获取配置Bean (以代码的方式配置sa-token, 此配置会覆盖yml中的配置)
|
||||
@Primary
|
||||
@Bean(name="MySaTokenConfig")
|
||||
public SaTokenConfig getSaTokenConfig() {
|
||||
SaTokenConfig config = new SaTokenConfig();
|
||||
config.setTokenName("satoken"); // token名称 (同时也是cookie名称)
|
||||
config.setTimeout(30 * 24 * 60 * 60); // token有效期,单位s 默认30天, -1代表永不过期
|
||||
config.setActivityTimeout(-1); // token临时有效期, 默认-1 代表不限制
|
||||
config.setIsShare(true); // 在多人登录同一账号时,是否共享会话 (为true时共用一个,为false时新登录挤掉旧登录)
|
||||
config.setIsReadBody(true); // 是否尝试从请求体里读取token
|
||||
config.setIsReadHead(true); // 是否尝试从header里读取token
|
||||
config.setIsReadCookie(true); // 是否尝试从cookie里读取token
|
||||
config.setTokenStyle("uuid"); // token风格
|
||||
config.setIsV(true); // 是否在初始化配置时打印版本字符画
|
||||
config.setTokenName("satoken"); // token名称 (同时也是cookie名称)
|
||||
config.setTimeout(30 * 24 * 60 * 60); // token有效期,单位s 默认30天
|
||||
config.setActivityTimeout(-1); // token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
|
||||
config.setAllowConcurrentLogin(true); // 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
|
||||
config.setIsShare(true); // 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
|
||||
config.setTokenStyle("uuid"); // token风格
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -69,14 +60,15 @@ spring:
|
||||
### 所有可配置项
|
||||
| 参数名称 | 类型 | 默认值 | 说明 |
|
||||
| :-------- | :-------- | :-------- | :-------- |
|
||||
| tokenName | String | satoken | token名称(同时也是cookie名称) |
|
||||
| tokenName | String | satoken | token名称 (同时也是cookie名称) |
|
||||
| timeout | long | 2592000 | token有效期,单位/秒 默认30天,-1代表永久有效 [参考:token有效期详解](/fun/token-timeout) |
|
||||
| activityTimeout | long | -1 | token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒, 默认-1 代表不限制 (例如可以设置为1800代表30分钟内无操作就过期) [参考:token有效期详解](/fun/token-timeout) |
|
||||
| isShare | Boolean | true | 在多人登录同一账号时,是否共享会话(为true时共用一个,为false时新登录挤掉旧登录) |
|
||||
| allowConcurrentLogin | Boolean | true | 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) |
|
||||
| isShare | Boolean | true | 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) |
|
||||
| isReadBody | Boolean | true | 是否尝试从请求体里读取token |
|
||||
| isReadHead | Boolean | true | 是否尝试从header里读取token |
|
||||
| isReadCookie | Boolean | true | 是否尝试从cookie里读取token |
|
||||
| tokenStyle | String | uuid | token风格, [参考:花式token](/use/token-style) |
|
||||
| dataRefreshPeriod | int | 30 | 默认dao层实现类中,每次清理过期数据间隔的时间 (单位: 秒) ,默认值30秒,设置为-1代表不启动定时清理 |
|
||||
| tokenSessionCheckLogin | Boolean | 30 | 获取token专属session时是否必须登录 |
|
||||
| tokenSessionCheckLogin | Boolean | true | 获取token专属session时是否必须登录 (如果配置为true,会在每次获取token专属session时校验是否登录) |
|
||||
| isV | Boolean | true | 是否在初始化配置时打印版本字符画 |
|
||||
|
@@ -1,146 +1,48 @@
|
||||
# 持久层扩展
|
||||
---
|
||||
- 每次重启项目就得重新登录一遍,我想把登录数据都放在`redis`里,这样重启项目也不用重新登录,行不行?**行!**
|
||||
- 你需要做的就是重写`sa-token`的dao层实现方式,参考以下方案:
|
||||
- 每次重启项目都需要重新登录一次,我想把会话数据都放在`Redis`、`MongoDB`等专业的缓存中间件中,这样重启项目也不用重新登录,行不行?**行!**
|
||||
- sa-token 在架构设计时将数据持久操作全部抽象到接口`SaTokenDao`中,此设计可以保证开发者对数据持久层的灵活扩展
|
||||
- 除了框架内部对`SaTokenDao`提供的基于内存的默认实现,官方仓库还提供了以下扩展方案:
|
||||
|
||||
|
||||
|
||||
### 1. 首先在pom.xml引入依赖
|
||||
### 1. sa-token 整合 Redis (使用jdk默认序列化方式)
|
||||
``` xml
|
||||
<!-- SpringBoot整合redis -->
|
||||
<!-- sa-token整合redis (使用jdk默认序列化方式) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-redis</artifactId>
|
||||
<version>RELEASE</version>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-dao-redis</artifactId>
|
||||
<version>1.8.0</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>1.8.0</version>
|
||||
</dependency>
|
||||
```
|
||||
优点:session序列化后可读性强,可灵活手动修改,缺点:兼容性稍差
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
**请注意,无论使用哪种序列化方式,你都必须为项目提供一个Redis实例化方案,例如:**
|
||||
``` xml
|
||||
<!-- 提供redis连接池 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
||||
### 2. 实现SaTokenDao接口
|
||||
新建文件`SaTokenDaoRedis.java`,实现接口`SaTokenDao`, 并加上注解`@Component`,保证此类被springboot扫描到
|
||||
- 代码参考:
|
||||
|
||||
```java
|
||||
package com.pj.satoken;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
|
||||
/**
|
||||
* sa-token持久层的实现类 , 基于redis
|
||||
*/
|
||||
@Component // 打开此注解,保证此类被springboot扫描,即可完成sa-token与redis的集成
|
||||
public class SaTokenDaoRedis implements SaTokenDao {
|
||||
<br><br>
|
||||
更多框架的集成方案正在更新中... (欢迎大家提交pr)
|
||||
|
||||
|
||||
// string专用
|
||||
@Autowired
|
||||
StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
// SaSession专用
|
||||
RedisTemplate<String, SaSession> redisTemplate;
|
||||
@Autowired
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void setRedisTemplate(RedisTemplate redisTemplate) {
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
|
||||
// 根据key获取value ,如果没有,则返回空
|
||||
@Override
|
||||
public String getValue(String key) {
|
||||
return stringRedisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
// 写入指定key-value键值对,并设定过期时间(单位:秒)
|
||||
@Override
|
||||
public void setValue(String key, String value, long timeout) {
|
||||
// 判断是否为永不过期
|
||||
if(timeout == SaTokenDao.NEVER_EXPIRE) {
|
||||
stringRedisTemplate.opsForValue().set(key, value);
|
||||
} else {
|
||||
stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新指定key-value键值对 (过期时间取原来的值)
|
||||
@Override
|
||||
public void updateValue(String key, String value) {
|
||||
long expire = getTimeout(key);
|
||||
if(expire == SaTokenDao.NOT_VALUE_EXPIRE) { // -2 = 无此键
|
||||
return;
|
||||
}
|
||||
this.setValue(key, value, expire);
|
||||
}
|
||||
|
||||
// 删除一个指定的key
|
||||
@Override
|
||||
public void deleteKey(String key) {
|
||||
stringRedisTemplate.delete(key);
|
||||
}
|
||||
|
||||
// 获取指定key的剩余存活时间 (单位: 秒)
|
||||
@Override
|
||||
public long getTimeout(String key) {
|
||||
return stringRedisTemplate.getExpire(key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 根据指定key的session,如果没有,则返回空
|
||||
@Override
|
||||
public SaSession getSession(String sessionId) {
|
||||
return redisTemplate.opsForValue().get(sessionId);
|
||||
}
|
||||
|
||||
// 将指定session持久化
|
||||
@Override
|
||||
public void saveSession(SaSession session, long timeout) {
|
||||
// 判断是否为永不过期
|
||||
if(timeout == SaTokenDao.NEVER_EXPIRE) {
|
||||
redisTemplate.opsForValue().set(session.getId(), session);
|
||||
} else {
|
||||
redisTemplate.opsForValue().set(session.getId(), session, timeout, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新指定session
|
||||
@Override
|
||||
public void updateSession(SaSession session) {
|
||||
long expire = getSessionTimeout(session.getId());
|
||||
if(expire == SaTokenDao.NOT_VALUE_EXPIRE) { // -2 = 无此键
|
||||
return;
|
||||
}
|
||||
this.saveSession(session, expire);
|
||||
}
|
||||
|
||||
// 删除一个指定的session
|
||||
@Override
|
||||
public void deleteSession(String sessionId) {
|
||||
redisTemplate.delete(sessionId);
|
||||
}
|
||||
|
||||
// 获取指定SaSession的剩余存活时间 (单位: 秒)
|
||||
@Override
|
||||
public long getSessionTimeout(String sessionId) {
|
||||
return redisTemplate.getExpire(sessionId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
- 可参考代码:[码云:SaTokenDaoRedis.java](https://gitee.com/sz6/sa-token/blob/master/sa-token-demo-springboot/src/main/java/com/pj/satoken/SaTokenDaoRedis.java)
|
||||
|
||||
|
@@ -30,7 +30,9 @@ import cn.dev33.satoken.stp.StpInterface;
|
||||
@Component // 保证此类被springboot扫描,完成sa-token的自定义权限验证扩展
|
||||
public class StpInterfaceImpl implements StpInterface {
|
||||
|
||||
// 返回一个账号所拥有的权限码集合
|
||||
/**
|
||||
* 返回一个账号所拥有的权限码集合
|
||||
*/
|
||||
@Override
|
||||
public List<Object> getPermissionCodeList(Object loginId, String loginKey) {
|
||||
List<Object> list = new ArrayList<Object>(); // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限
|
||||
@@ -43,6 +45,17 @@ public class StpInterfaceImpl implements StpInterface {
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
|
||||
*/
|
||||
@Override
|
||||
public List<String> getRoleList(Object loginId, String loginKey) {
|
||||
List<String> list = new ArrayList<String>(); // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询角色
|
||||
list.add("admin");
|
||||
list.add("super-admin");
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
@@ -1,21 +1,16 @@
|
||||
# 踢人下线
|
||||
所谓踢人下线,核心操作就是找到其指定`loginId`的token,并设置其失效
|
||||
|
||||
---
|
||||
|
||||
|
||||
## 核心思想
|
||||
|
||||
- 所谓踢人下线,核心操作就是找到其指定`loginId`的token,并设置其失效
|
||||
|
||||
|
||||
## 具体API
|
||||
|
||||
#### StpUtil.logoutByLoginId(Object loginId)
|
||||
- 让指定loginId的会话注销登录(清退下线)
|
||||
让指定loginId的会话注销登录(踢人下线),例如:
|
||||
|
||||
#### StpUtil.kickoutByLoginId(Object loginId)
|
||||
- 让指定loginId的会话注销登录(踢人下线)
|
||||
``` java
|
||||
// 使账号id为10001的会话注销登录,待到10001再次访问系统时会抛出`NotLoginException`异常,场景值为-5
|
||||
StpUtil.logoutByLoginId(10001);
|
||||
```
|
||||
|
||||
## 详解
|
||||
- `logoutByLoginId` 和 `kickoutByLoginId` 都可以将用户强制下线,不同点在于:
|
||||
- `logoutByLoginId` 是将人清退,用户得到的提示是 [token无效] ,对于失效原因尚未可知 (NotLoginException场景值为-2)
|
||||
- `kickoutByLoginId` 是将人踢下线,用户可得到明确提示 [已被踢下线] (NotLoginException场景值为-5)
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
## 核心思想
|
||||
- sa-token在设计时充分考虑了多账号体系时的各种逻辑
|
||||
- 以上几篇介绍的api,都是经过 `StpUtil`类的各种静态方法进行各种验证,而如果你深入它的源码,[点此阅览](https://gitee.com/sz6/sa-token/blob/master/sa-token-dev/src/main/java/cn/dev33/satoken/stp/StpUtil.java)
|
||||
- 以上几篇介绍的api,都是经过 `StpUtil`类的各种静态方法进行各种验证,而如果你深入它的源码,[点此阅览](https://gitee.com/sz6/sa-token/blob/master/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpUtil.java)
|
||||
- 就会发现,此类并没有任何代码逻辑,唯一做的事就是对成员变量`stpLogic`的各个API进行包装一下进行转发
|
||||
- 这样做有两个优点
|
||||
- `StpLogic`类的所有函数都可以被重写,按需扩展
|
||||
@@ -19,7 +19,7 @@
|
||||
1. 新建一个新的权限验证类,比如: `StpUserUtil.java`
|
||||
2. 将`StpUtil.java`类的全部代码复制粘贴到 `StpUserUtil.java`里
|
||||
3. 更改一下其 `loginKey`, 比如:
|
||||
```
|
||||
``` java
|
||||
// 底层的 StpLogic 对象
|
||||
public static StpLogic stpLogic = new StpLogic("user"); // loginKey改为user
|
||||
```
|
||||
|
@@ -19,10 +19,10 @@
|
||||
- 类似API还有:
|
||||
- `StpUtil.getSessionByLoginId(Object loginId, boolean isCreate)` 获取当前会话登录id, `isCreate`代表指定是否在无`session`的情况下新建并返回
|
||||
|
||||
#### StpUtil.hasRole(Object loginId, Object role)
|
||||
#### StpUtil.hasRole(Object loginId, String role)
|
||||
- 指定`loginId`是否含有指定角色
|
||||
|
||||
#### StpUtil.hasPermission(Object loginId, Object permission)
|
||||
#### StpUtil.hasPermission(Object loginId, String permission)
|
||||
- 指定`loginId`是否含有指定权限
|
||||
|
||||
|
||||
|
@@ -1,37 +1,58 @@
|
||||
# session会话
|
||||
# Session会话
|
||||
---
|
||||
|
||||
|
||||
## 账号session
|
||||
账号`session`指的是为每个登录账号分配的`session`
|
||||
|
||||
#### StpUtil.getSession()
|
||||
- 返回当前登录账号的`session`(必须是登录后才能调用)
|
||||
Session是会话中专业的数据缓存组件,在`sa-token`中Session分为三种, 分别是:
|
||||
- `账号Session`: 指的是框架为每个`loginId`分配的`Session`
|
||||
- `令牌Session`: 指的是框架为每个`token`分配的`Session`
|
||||
- `自定义Session`: 指的是以一个`特定的值`作为SessionId,来分配的`Session`
|
||||
|
||||
|
||||
## 自定义session
|
||||
自定义`session`指的是未登录状态下,以一个特定的值作为key,来分配的`session`
|
||||
|
||||
#### SaSessionCustomUtil.isExists(String sessionId)
|
||||
- 查询指定key的`session`,是否存在
|
||||
|
||||
#### SaSessionCustomUtil.getSessionById(String sessionId)
|
||||
- 获取指定key的`session`,如果没有,则新建并返回
|
||||
|
||||
#### SaSessionCustomUtil.delSessionById(String sessionId)
|
||||
- 删除指定key的`session`
|
||||
## 账号Session
|
||||
有关账号Session的API如下:
|
||||
``` java
|
||||
StpUtil.getSession(); // 获取当前账号id的Session (必须是登录后才能调用)
|
||||
StpUtil.getSession(true); // 获取当前账号id的Session, 并决定在Session尚未创建时,是否新建并返回
|
||||
StpUtil.getSessionByLoginId(10001); // 获取账号id为10001的Session
|
||||
StpUtil.getSessionByLoginId(10001, true); // 获取账号id为10001的Session, 并决定在Session尚未创建时,是否新建并返回
|
||||
```
|
||||
|
||||
|
||||
## session相关操作
|
||||
## 令牌Session
|
||||
有关令牌Session的API如下:
|
||||
``` java
|
||||
StpUtil.getTokenSession(); // 获取当前token的专属Session
|
||||
StpUtil.getTokenSessionByToken(token); // 获取指定token的专属Session
|
||||
```
|
||||
|
||||
|
||||
## 自定义Session
|
||||
自定义Session指的是以一个`特定的值`作为SessionId来分配的`Session`, 借助自定义Session,你可以为系统中的任意元素分配相应的session<br>
|
||||
例如以商品id作为key为每个商品分配一个Session,以便于缓存和商品相关的数据,其相关API如下:
|
||||
``` java
|
||||
SaSessionCustomUtil.isExists("goods-10001"); // 查询指定key的Session是否存在
|
||||
SaSessionCustomUtil.getSessionById("goods-10001"); // 获取指定key的Session,如果没有,则新建并返回
|
||||
SaSessionCustomUtil.getSessionById("goods-10001", false); // 获取指定key的Session,如果没有,第二个参数决定是否新建并返回
|
||||
SaSessionCustomUtil.deleteSessionById("goods-10001"); // 删除指定key的Session
|
||||
```
|
||||
在未登录状态下是否可以获取令牌Session?这取决于你配置的`tokenSessionCheckLogin`值是否为false,详见:[框架配置](/use/config?id=所有可配置项)
|
||||
|
||||
|
||||
## Session相关操作
|
||||
那么获取到的`SaSession`具体有哪些方法可供操作?
|
||||
``` java
|
||||
session.getId(); // 返回此Session的id
|
||||
session.getCreateTime(); // 返回此Session的创建时间 (时间戳)
|
||||
session.getAttribute('name'); // 在Session上获取一个值
|
||||
session.getAttribute('name', 'zhang'); // 在Session上获取一个值,并指定取不到值时返回的默认值
|
||||
session.setAttribute('name', 'zhang'); // 在Session上写入一个值
|
||||
session.removeAttribute('name'); // 在Session上移除一个值
|
||||
session.clearAttribute(); // 清空此Session的所有值
|
||||
session.containsAttribute('name'); // 获取此Session是否含有指定key (返回true或false)
|
||||
session.attributeKeys(); // 获取此Session会话上所有key (返回Set<String>)
|
||||
session.getDataMap(); // 返回此Session会话上的底层数据对象(如果更新map里的值,请调用session.update()方法避免数据过时)
|
||||
session.update(); // 将这个Session从持久库更新一下
|
||||
session.logout(); // 注销此Session会话
|
||||
```
|
||||
具体可参考`javax.servlet.http.HttpSession`,`SaSession`所含方法与其大体类似
|
||||
|
||||
#### getId()
|
||||
- 返回此`session`的id
|
||||
|
||||
#### setAttribute(String key, Object value)
|
||||
- 在此`session`对象上写入值
|
||||
|
||||
#### getAttribute(String key)
|
||||
- 在此`session`对象上查询值
|
||||
|
||||
具体可参考`javax.servlet.http.HttpSession`,`SaSession`所含方法与其大体类似
|
@@ -81,6 +81,7 @@
|
||||
|
||||
1. 首先我们需要找一个合适的类库,帮助我们生成雪花算法唯一id,在此推荐 [Hutool](https://hutool.cn/docs/#/) ,在`pom.xml`里添加依赖:
|
||||
``` xml
|
||||
<!-- Hutool 一个小而全的Java工具类库 -->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
|
Reference in New Issue
Block a user