mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-08-23 22:11:29 +08:00
优化文档:session会话
This commit is contained in:
parent
fcd2ca7f8d
commit
4887777315
@ -10,7 +10,7 @@
|
||||
- [登录认证](/use/login-auth)
|
||||
- [权限认证](/use/jur-auth)
|
||||
- [踢人下线](/use/kick)
|
||||
- [注解式鉴权](/use/at-check)
|
||||
- [注解鉴权](/use/at-check)
|
||||
- [路由拦截鉴权](/use/route-check)
|
||||
- [Session会话](/use/session)
|
||||
- [框架配置](/use/config)
|
||||
|
@ -1,25 +1,25 @@
|
||||
# 注解式鉴权
|
||||
# 注解鉴权
|
||||
---
|
||||
|
||||
有同学表示:尽管使用代码鉴权非常方便,但是我仍希望把鉴权逻辑和业务逻辑分离开来,我可以使用注解鉴权吗?当然可以!<br>
|
||||
|
||||
注解鉴权 —— 优雅的将鉴权与业务代码分离!
|
||||
|
||||
- `@SaCheckLogin`: 登录认证 —— 只有登录之后才能进入该方法
|
||||
- `@SaCheckRole("admin")`: 角色认证 —— 必须具有指定角色标识才能进入该方法
|
||||
- `@SaCheckPermission("user:add")`: 权限认证 —— 必须具有指定权限才能进入该方法
|
||||
- `@SaCheckSafe`: 二级认证校验 —— 必须二级认证之后才能进入该方法
|
||||
- `@SaCheckBasic`: HttpBasic认证 —— 只有通过 Basic 认证后才能进入该方法
|
||||
- `@SaCheckLogin`: 登录认证 —— 只有登录之后才能进入该方法。
|
||||
- `@SaCheckRole("admin")`: 角色认证 —— 必须具有指定角色标识才能进入该方法。
|
||||
- `@SaCheckPermission("user:add")`: 权限认证 —— 必须具有指定权限才能进入该方法。
|
||||
- `@SaCheckSafe`: 二级认证校验 —— 必须二级认证之后才能进入该方法。
|
||||
- `@SaCheckBasic`: HttpBasic认证 —— 只有通过 Basic 认证后才能进入该方法。
|
||||
|
||||
Sa-Token使用全局拦截器完成注解鉴权功能,为了不为项目带来不必要的性能负担,拦截器默认处于关闭状态<br>
|
||||
因此,为了使用注解鉴权,你必须手动将Sa-Token的全局拦截器注册到你项目中
|
||||
Sa-Token 使用全局拦截器完成注解鉴权功能,为了不为项目带来不必要的性能负担,拦截器默认处于关闭状态<br>
|
||||
因此,为了使用注解鉴权,**你必须手动将 Sa-Token 的全局拦截器注册到你项目中**
|
||||
|
||||
<!-- Sa-Token内置两种模式完成注解鉴权,分别是`拦截器模式`和`AOP模式`, 为了避免不必要的性能浪费,这两种模式默认都处于关闭状态 <br>
|
||||
因此如若使用注解鉴权,你必须选择其一进行注册 -->
|
||||
|
||||
|
||||
### 1、注册拦截器
|
||||
以`SpringBoot2.0`为例, 新建配置类`SaTokenConfigure.java`
|
||||
以`SpringBoot2.0`为例,新建配置类`SaTokenConfigure.java`
|
||||
|
||||
``` java
|
||||
@Configuration
|
||||
@ -38,7 +38,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
||||
|
||||
|
||||
### 2、使用注解鉴权
|
||||
然后我们就可以愉快的使用注解鉴权:
|
||||
然后我们就可以愉快的使用注解鉴权了:
|
||||
|
||||
``` java
|
||||
// 登录认证:只有登录之后才能进入该方法
|
||||
@ -92,12 +92,12 @@ public SaResult atJurOr() {
|
||||
```
|
||||
|
||||
mode有两种取值:
|
||||
- `SaMode.AND`, 标注一组权限,会话必须全部具有才可通过校验
|
||||
- `SaMode.OR`, 标注一组权限,会话只要具有其一即可通过校验
|
||||
- `SaMode.AND`, 标注一组权限,会话必须全部具有才可通过校验。
|
||||
- `SaMode.OR`, 标注一组权限,会话只要具有其一即可通过校验。
|
||||
|
||||
|
||||
### 4、角色权限双重 “or校验”
|
||||
假设有以下业务场景:一个接口在具体权限 `user-add` 或角色 `admin` 时可以调通。怎么写?
|
||||
假设有以下业务场景:一个接口在具有权限 `user-add` 或角色 `admin` 时可以调通。怎么写?
|
||||
|
||||
``` java
|
||||
// 注解式鉴权:只要具有其中一个权限即可通过校验
|
||||
|
@ -1,5 +1,5 @@
|
||||
# 踢人下线
|
||||
所谓踢人下线,核心操作就是找到其指定`loginId`对应的`token`,并设置其失效
|
||||
所谓踢人下线,核心操作就是找到指定 `loginId` 对应的 `Token`,并设置其失效。
|
||||
|
||||

|
||||
|
||||
|
@ -2,9 +2,10 @@
|
||||
---
|
||||
|
||||
假设我们有如下需求:
|
||||
> 项目中所有接口均需要登录认证,只有'登录接口'本身对外开放
|
||||
> 项目中所有接口均需要登录认证,只有 '登录接口' 本身对外开放
|
||||
|
||||
我们怎么实现呢?给每个接口加上鉴权注解?手写全局拦截器?似乎都不是非常方便。
|
||||
|
||||
我们怎么实现呢?给每个接口加上鉴权注解?手写全局拦截器?似乎都不是非常方便。<br/>
|
||||
在这个需求中我们真正需要的是一种基于路由拦截的鉴权模式, 那么在Sa-Token怎么实现路由拦截鉴权呢?
|
||||
|
||||
|
||||
@ -17,26 +18,27 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
||||
// 注册拦截器
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// 注册Sa-Token的路由拦截器
|
||||
// 注册 Sa-Token 的路由拦截器
|
||||
registry.addInterceptor(new SaRouteInterceptor())
|
||||
.addPathPatterns("/**")
|
||||
.excludePathPatterns("/user/doLogin");
|
||||
}
|
||||
}
|
||||
```
|
||||
以上代码,我们注册了一个登录认证拦截器,并且排除了`/user/doLogin`接口用来开放登录(除了`/user/doLogin`以外的所有接口都需要登录才能访问) <br>
|
||||
那么我们如何进行权限认证拦截呢,且往下看
|
||||
以上代码,我们注册了一个登录认证拦截器,并且排除了`/user/doLogin`接口用来开放登录(除了`/user/doLogin`以外的所有接口都需要登录才能访问)。
|
||||
|
||||
|
||||
### 2、校验函数详解
|
||||
你可以使用函数式编程自定义认证规则,例如:
|
||||
自定义认证规则:`new SaRouteInterceptor()` 是最简单的无参构造写法,代表只进行默认的登录校验功能。
|
||||
|
||||
我们可以往构造函数塞一个 lambda 表达式,来自定义认证规则,例如:
|
||||
|
||||
``` java
|
||||
@Configuration
|
||||
public class SaTokenConfigure implements WebMvcConfigurer {
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// 注册路由拦截器,自定义认证规则
|
||||
// 注册 Sa-Token 的路由拦截器,自定义认证规则
|
||||
registry.addInterceptor(new SaRouteInterceptor((req, res, handler)->{
|
||||
// 根据路由划分模块,不同模块不同鉴权
|
||||
SaRouter.match("/user/**", r -> StpUtil.checkPermission("user"));
|
||||
|
@ -19,7 +19,7 @@ SysUser user = (SysUser) StpUtil.getSession().get("user");
|
||||
- `Token-Session`: 指的是框架为每个 token 分配的 Session
|
||||
- `Custom-Session`: 指的是以一个 特定的值 作为SessionId,来分配的 Session
|
||||
|
||||
> 有关User-Session与Token-Session的详细区别,请参考:[Session模型详解](/fun/session-model)
|
||||
> 有关User-Session与Token-Session的详细区别,可参考:[Session模型详解](/fun/session-model)
|
||||
|
||||
|
||||
### User-Session
|
||||
@ -72,50 +72,8 @@ SaSessionCustomUtil.deleteSessionById("goods-10001");
|
||||
```
|
||||
|
||||
|
||||
### Session相关操作
|
||||
那么获取到的`SaSession`具体有哪些方法可供操作?
|
||||
``` java
|
||||
// 返回此Session的id
|
||||
session.getId();
|
||||
### 在 Session 上存取值
|
||||
|
||||
// 返回此Session的创建时间 (时间戳)
|
||||
session.getCreateTime();
|
||||
|
||||
// 在Session上获取一个值
|
||||
session.getAttribute('name');
|
||||
|
||||
// 在Session上获取一个值,并指定取不到值时返回的默认值
|
||||
session.getAttribute('name', 'zhang');
|
||||
|
||||
// 在Session上写入一个值
|
||||
session.setAttribute('name', 'zhang');
|
||||
|
||||
// 在Session上移除一个值
|
||||
session.removeAttribute('name');
|
||||
|
||||
// 清空此Session的所有值
|
||||
session.clearAttribute();
|
||||
|
||||
// 获取此Session是否含有指定key (返回true或false)
|
||||
session.containsAttribute('name');
|
||||
|
||||
// 获取此Session会话上所有key (返回Set<String>)
|
||||
session.attributeKeys();
|
||||
|
||||
// 返回此Session会话上的底层数据对象(如果更新map里的值,请调用session.update()方法避免产生脏数据)
|
||||
session.getDataMap();
|
||||
|
||||
// 将这个Session从持久库更新一下
|
||||
session.update();
|
||||
|
||||
// 注销此Session会话 (从持久库删除此Session)
|
||||
session.logout();
|
||||
```
|
||||
|
||||
|
||||
### 类型转换API
|
||||
由于Session存取值默认的类型都是Object,因此我们通常会写很多不必要类型转换代码 <br>
|
||||
为了简化操作,Sa-Token自`v1.15.0`封装了存取值API的类型转换,你可以非常方便的调用以下方法:
|
||||
``` java
|
||||
// 写值
|
||||
session.set("name", "zhang");
|
||||
@ -129,29 +87,46 @@ session.get("name");
|
||||
// 取值 (指定默认值)
|
||||
session.get("name", "<defaultValue>");
|
||||
|
||||
// 取值 (转String类型)
|
||||
session.getString("name");
|
||||
// ---------- 数据类型转换: ----------
|
||||
session.getInt("age"); // 取值 (转int类型)
|
||||
session.getLong("age"); // 取值 (转long类型)
|
||||
session.getString("name"); // 取值 (转String类型)
|
||||
session.getDouble("result"); // 取值 (转double类型)
|
||||
session.getFloat("result"); // 取值 (转float类型)
|
||||
session.getModel("key", Student.class); // 取值 (指定转换类型)
|
||||
session.getModel("key", Student.class, <defaultValue>); // 取值 (指定转换类型, 并指定值为Null时返回的默认值)
|
||||
|
||||
// 取值 (转int类型)
|
||||
session.getInt("age");
|
||||
|
||||
// 取值 (转long类型)
|
||||
session.getLong("age");
|
||||
|
||||
// 取值 (转double类型)
|
||||
session.getDouble("result");
|
||||
|
||||
// 取值 (转float类型)
|
||||
session.getFloat("result");
|
||||
|
||||
// 取值 (指定转换类型)
|
||||
session.getModel("key", Student.class);
|
||||
|
||||
// 取值 (指定转换类型, 并指定值为Null时返回的默认值)
|
||||
session.getModel("key", Student.class, <defaultValue>);
|
||||
|
||||
// 是否含有某个key
|
||||
// 是否含有某个key (返回true或false)
|
||||
session.has("key");
|
||||
|
||||
// 删值
|
||||
session.delete('name');
|
||||
|
||||
// 清空所有值
|
||||
session.clear();
|
||||
|
||||
// 获取此 Session 的所有key (返回Set<String>)
|
||||
session.keys();
|
||||
```
|
||||
|
||||
|
||||
### 其它操作
|
||||
|
||||
``` java
|
||||
// 返回此 Session 的id
|
||||
session.getId();
|
||||
|
||||
// 返回此 Session 的创建时间 (时间戳)
|
||||
session.getCreateTime();
|
||||
|
||||
// 返回此 Session 会话上的底层数据对象(如果更新map里的值,请调用session.update()方法避免产生脏数据)
|
||||
session.getDataMap();
|
||||
|
||||
// 将这个 Session 从持久库更新一下
|
||||
session.update();
|
||||
|
||||
// 注销此 Session 会话 (从持久库删除此Session)
|
||||
session.logout();
|
||||
```
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user