mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-09-19 10:08:07 +08:00
优化文档
This commit is contained in:
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<!-- springboot依赖 -->
|
<!-- SpringBoot依赖 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
@@ -38,14 +38,14 @@
|
|||||||
<version>${sa-token-version}</version>
|
<version>${sa-token-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- sa-token整合redis (使用jackson序列化方式) -->
|
<!-- Sa-Token 整合Redis (使用jackson序列化方式) -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.dev33</groupId>
|
<groupId>cn.dev33</groupId>
|
||||||
<artifactId>sa-token-dao-redis-jackson</artifactId>
|
<artifactId>sa-token-dao-redis-jackson</artifactId>
|
||||||
<version>${sa-token-version}</version>
|
<version>${sa-token-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 提供redis连接池 -->
|
<!-- 提供Redis连接池 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-pool2</artifactId>
|
<artifactId>commons-pool2</artifactId>
|
||||||
|
@@ -26,18 +26,18 @@
|
|||||||
|
|
||||||
|
|
||||||
## Sa-Token 介绍
|
## Sa-Token 介绍
|
||||||
Sa-Token是一个轻量级Java权限认证框架,主要解决:登录认证、权限认证、Session会话、单点登录、OAuth2.0 等一系列权限相关问题
|
Sa-Token是一个轻量级Java权限认证框架,主要解决:登录认证、权限认证、Session会话、单点登录、OAuth2.0、微服务网关鉴权 等一系列权限相关问题
|
||||||
|
|
||||||
框架集成简单、开箱即用、API设计清爽,通过Sa-Token,你将以一种极其简单的方式实现系统的权限认证部分
|
框架集成简单、开箱即用、API设计清爽,通过Sa-Token,你将以一种极其简单的方式实现系统的权限认证部分
|
||||||
|
|
||||||
- **登录验证** —— 单端登录、多端登录、同端互斥登录、七天内免登录
|
- **登录认证** —— 单端登录、多端登录、同端互斥登录、七天内免登录
|
||||||
- **权限验证** —— 权限认证、角色认证、会话二级认证
|
- **权限认证** —— 权限认证、角色认证、会话二级认证
|
||||||
- **Session会话** —— 全端共享Session、单端独享Session、自定义Session
|
- **Session会话** —— 全端共享Session、单端独享Session、自定义Session
|
||||||
- **踢人下线** —— 根据账号id踢人下线、根据Token值踢人下线
|
- **踢人下线** —— 根据账号id踢人下线、根据Token值踢人下线
|
||||||
- **账号封禁** —— 指定天数封禁、永久封禁、设定解封时间
|
- **账号封禁** —— 指定天数封禁、永久封禁、设定解封时间
|
||||||
- **持久层扩展** —— 可集成Redis、Memcached等专业缓存中间件,重启数据不丢失
|
- **持久层扩展** —— 可集成Redis、Memcached等专业缓存中间件,重启数据不丢失
|
||||||
- **分布式会话** —— 提供jwt集成、共享数据中心两种分布式会话方案
|
- **分布式会话** —— 提供jwt集成、共享数据中心两种分布式会话方案
|
||||||
- **微服务网关鉴权** —— 适配Gateway、Soul、Zuul等常见网关的路由拦截认证
|
- **微服务网关鉴权** —— 适配Gateway、ShenYu、Zuul等常见网关的路由拦截认证
|
||||||
- **单点登录** —— 内置三种单点登录模式:无论是否跨域、是否共享Redis,都可以搞定
|
- **单点登录** —— 内置三种单点登录模式:无论是否跨域、是否共享Redis,都可以搞定
|
||||||
- **二级认证** —— 在已登录的基础上再次认证,保证安全性
|
- **二级认证** —— 在已登录的基础上再次认证,保证安全性
|
||||||
- **独立Redis** —— 将权限缓存与业务缓存分离
|
- **独立Redis** —— 将权限缓存与业务缓存分离
|
||||||
|
@@ -86,7 +86,7 @@
|
|||||||
- 新增:新增基于`ThreadLocal`的上下文容器 **[重要]**
|
- 新增:新增基于`ThreadLocal`的上下文容器 **[重要]**
|
||||||
- 新增:新增`Reactor`响应式编程支持,`WebFlux`集成! **[重要]**
|
- 新增:新增`Reactor`响应式编程支持,`WebFlux`集成! **[重要]**
|
||||||
- 新增:新增全局过滤器,解决拦截器无法拦截静态资源的问题 **[重要]**
|
- 新增:新增全局过滤器,解决拦截器无法拦截静态资源的问题 **[重要]**
|
||||||
- 新增:新增微服务网关鉴权方案!可接入`Soul`、`Gateway`等网关组件! **[重要]**
|
- 新增:新增微服务网关鉴权方案!可接入`ShenYu`、`Gateway`等网关组件! **[重要]**
|
||||||
- 新增:AOP切面定义`Order`顺序为`-100`,可保证在多个自定义切面前执行
|
- 新增:AOP切面定义`Order`顺序为`-100`,可保证在多个自定义切面前执行
|
||||||
- 文档:新增推荐公众号列表
|
- 文档:新增推荐公众号列表
|
||||||
|
|
||||||
|
@@ -26,7 +26,7 @@ Sa-Token 在集群、分布式下的解决方案
|
|||||||
|
|
||||||
|
|
||||||
### 微服务网关鉴权
|
### 微服务网关鉴权
|
||||||
由于大多数常见网关组件基于`webflux`编写,从底层上脱离了"ServletAPI"模型(如`Gateway`、`Soul`等),这就导致很多底层依赖ServletAPI的权限认证框架无法在网关处使用。
|
由于大多数常见网关组件基于`webflux`编写,从底层上脱离了"ServletAPI"模型(如`Gateway`、`ShenYu`等),这就导致很多底层依赖ServletAPI的权限认证框架无法在网关处使用。
|
||||||
|
|
||||||
为此`Sa-Token`自`v1.16.0`版本开始提供了`Reactor响应式模型`web框架的starter依赖包,你可以据此轻松完成网关鉴权需求,
|
为此`Sa-Token`自`v1.16.0`版本开始提供了`Reactor响应式模型`web框架的starter依赖包,你可以据此轻松完成网关鉴权需求,
|
||||||
详细请参考:[全局过滤器](/use/global-filter)
|
详细请参考:[全局过滤器](/use/global-filter)
|
||||||
@@ -44,7 +44,7 @@ Sa-Token 在集群、分布式下的解决方案
|
|||||||
|
|
||||||
对于网关服务,大体来讲分为两种:
|
对于网关服务,大体来讲分为两种:
|
||||||
- 一种是基于Servlet模型的,如:Zuul,我们需要引入的是:`sa-token-spring-boot-starter`,详细戳:[在SpringBoot环境集成](/start/example)
|
- 一种是基于Servlet模型的,如:Zuul,我们需要引入的是:`sa-token-spring-boot-starter`,详细戳:[在SpringBoot环境集成](/start/example)
|
||||||
- 一种是基于Reactor模型的,如:SpringCloud Gateway、Soul 等等,我们需要引入的是:`sa-token-reactor-spring-boot-starter`,**并且注册全局过滤器!**,详细戳:[在WebFlux环境集成](/start/webflux-example)
|
- 一种是基于Reactor模型的,如:SpringCloud Gateway、ShenYu 等等,我们需要引入的是:`sa-token-reactor-spring-boot-starter`,**并且注册全局过滤器!**,详细戳:[在WebFlux环境集成](/start/webflux-example)
|
||||||
|
|
||||||
切不可直接在一个项目里同时引入这两个依赖,否则会造成项目无法启动
|
切不可直接在一个项目里同时引入这两个依赖,否则会造成项目无法启动
|
||||||
|
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
```
|
```
|
||||||
|
|
||||||
<!-- tab:WebFlux环境 (Reactor) -->
|
<!-- tab:WebFlux环境 (Reactor) -->
|
||||||
注:如果你使用的框架基于 Reactor 模型构建(Netty、WebFlux、Soul、SC Gateway等),请引入此包
|
注:如果你使用的框架基于 Reactor 模型构建(Netty、WebFlux、ShenYu、SC Gateway等),请引入此包
|
||||||
``` xml
|
``` xml
|
||||||
<!-- Sa-Token 权限认证(Reactor响应式集成), 在线文档:http://sa-token.dev33.cn/ -->
|
<!-- Sa-Token 权限认证(Reactor响应式集成), 在线文档:http://sa-token.dev33.cn/ -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
# Spring WebFlux 集成 Sa-Token 示例
|
# Spring WebFlux 集成 Sa-Token 示例
|
||||||
|
|
||||||
WebFlux基于Reactor响应式模型开发,有着与标准ServletAPI完全不同的底层架构,因此要适配WebFlux, 必须提供与Reactor相关的整合实现,
|
WebFlux基于Reactor响应式模型开发,有着与标准ServletAPI完全不同的底层架构,因此要适配WebFlux, 必须提供与Reactor相关的整合实现,
|
||||||
本篇将以WebFlux为例,展示Sa-Token与Reactor响应式模型web框架相整合的示例, **你可以用同样方式去对接其它Reactor模型Web框架**(Netty、Soul、Gateway等)
|
本篇将以WebFlux为例,展示Sa-Token与Reactor响应式模型web框架相整合的示例, **你可以用同样方式去对接其它Reactor模型Web框架**(Netty、ShenYu、Gateway等)
|
||||||
|
|
||||||
整合示例在官方仓库的`/sa-token-demo/sa-token-demo-webflux`文件夹下,如遇到难点可结合源码进行测试学习
|
整合示例在官方仓库的`/sa-token-demo/sa-token-demo-webflux`文件夹下,如遇到难点可结合源码进行测试学习
|
||||||
|
|
||||||
|
@@ -116,7 +116,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="feature">
|
<div class="feature">
|
||||||
<h2>微服务网关鉴权</h2>
|
<h2>微服务网关鉴权</h2>
|
||||||
<p>适配Gateway、Soul、Zuul等常见网关组件的请求拦截认证</p>
|
<p>适配Gateway、ShenYu、Zuul等常见网关组件的请求拦截认证</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="feature">
|
<div class="feature">
|
||||||
<h2>单点登录</h2>
|
<h2>单点登录</h2>
|
||||||
@@ -256,8 +256,8 @@
|
|||||||
<br>
|
<br>
|
||||||
<h2 class="s-title">友情链接</h2>
|
<h2 class="s-title">友情链接</h2>
|
||||||
<div class="com-box com-box-you">
|
<div class="com-box com-box-you">
|
||||||
<a href="https://gitee.com/dromara/soul" target="_blank">
|
<a href="https://gitee.com/Apache-ShenYu/incubator-shenyu" target="_blank">
|
||||||
<img src="https://oss.dev33.cn/sa-token/link/soul.png" msg="JAVA语言中可扩展,高性能,响应式的 API 网关">
|
<img src="https://oss.dev33.cn/sa-token/link/shenyu.png" msg="JAVA语言中可扩展,高性能,响应式的 API 网关">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://gitee.com/dromara/TLog" target="_blank">
|
<a href="https://gitee.com/dromara/TLog" target="_blank">
|
||||||
<img src="https://oss.dev33.cn/sa-token/link/tlog2.png" msg="一个轻量级的分布式日志标记追踪神器,10分钟即可接入,自动对日志打标签完成微服务的链路追踪">
|
<img src="https://oss.dev33.cn/sa-token/link/tlog2.png" msg="一个轻量级的分布式日志标记追踪神器,10分钟即可接入,自动对日志打标签完成微服务的链路追踪">
|
||||||
|
@@ -43,71 +43,78 @@ public class SaAloneRedisInject implements EnvironmentAware{
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setEnvironment(Environment environment) {
|
public void setEnvironment(Environment environment) {
|
||||||
|
|
||||||
// 如果为空或者默认实现,则不进行任何操作
|
|
||||||
if(saTokenDao == null || saTokenDao instanceof SaTokenDaoDefaultImpl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------- 开始注入
|
|
||||||
|
|
||||||
// 获取cfg对象
|
|
||||||
RedisProperties cfg = Binder.get(environment).bind(ALONE_PREFIX, RedisProperties.class).get();
|
|
||||||
|
|
||||||
// 1. Redis配置
|
|
||||||
RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
|
|
||||||
redisConfig.setHostName(cfg.getHost());
|
|
||||||
redisConfig.setPort(cfg.getPort());
|
|
||||||
redisConfig.setDatabase(cfg.getDatabase());
|
|
||||||
redisConfig.setPassword(RedisPassword.of(cfg.getPassword()));
|
|
||||||
|
|
||||||
// 2. 连接池配置
|
|
||||||
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
|
|
||||||
// pool配置
|
|
||||||
Lettuce lettuce = cfg.getLettuce();
|
|
||||||
if(lettuce.getPool() != null) {
|
|
||||||
RedisProperties.Pool pool = cfg.getLettuce().getPool();
|
|
||||||
// 连接池最大连接数
|
|
||||||
poolConfig.setMaxTotal(pool.getMaxActive());
|
|
||||||
// 连接池中的最大空闲连接
|
|
||||||
poolConfig.setMaxIdle(pool.getMaxIdle());
|
|
||||||
// 连接池中的最小空闲连接
|
|
||||||
poolConfig.setMinIdle(pool.getMinIdle());
|
|
||||||
// 连接池最大阻塞等待时间(使用负值表示没有限制)
|
|
||||||
poolConfig.setMaxWaitMillis(pool.getMaxWait().toMillis());
|
|
||||||
}
|
|
||||||
LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder();
|
|
||||||
// timeout
|
|
||||||
if(cfg.getTimeout() != null) {
|
|
||||||
builder.commandTimeout(cfg.getTimeout());
|
|
||||||
}
|
|
||||||
// shutdownTimeout
|
|
||||||
if(lettuce.getShutdownTimeout() != null) {
|
|
||||||
builder.shutdownTimeout(lettuce.getShutdownTimeout());
|
|
||||||
}
|
|
||||||
// 创建Factory对象
|
|
||||||
LettuceClientConfiguration clientConfig = builder.poolConfig(poolConfig).build();
|
|
||||||
LettuceConnectionFactory factory = new LettuceConnectionFactory(redisConfig, clientConfig);
|
|
||||||
factory.afterPropertiesSet();
|
|
||||||
|
|
||||||
// 3. 开始初始化 SaTokenDao
|
|
||||||
// 如果是SaTokenDaoRedis
|
|
||||||
try {
|
try {
|
||||||
Class.forName("cn.dev33.satoken.dao.SaTokenDaoRedis");
|
// 如果为空或者默认实现,则不进行任何操作
|
||||||
SaTokenDaoRedis dao = (SaTokenDaoRedis)saTokenDao;
|
if(saTokenDao == null || saTokenDao instanceof SaTokenDaoDefaultImpl) {
|
||||||
dao.isInit = false;
|
return;
|
||||||
dao.init(factory);
|
}
|
||||||
return;
|
// 如果配置文件不包含相关配置,则不进行任何操作
|
||||||
} catch (ClassNotFoundException e) {
|
if(environment.getProperty(ALONE_PREFIX + ".host") == null) {
|
||||||
}
|
return;
|
||||||
// 如果是SaTokenDaoRedisJackson
|
}
|
||||||
try {
|
|
||||||
Class.forName("cn.dev33.satoken.dao.SaTokenDaoRedisJackson");
|
// ------------------- 开始注入
|
||||||
SaTokenDaoRedisJackson dao = (SaTokenDaoRedisJackson)saTokenDao;
|
|
||||||
dao.isInit = false;
|
// 获取cfg对象
|
||||||
dao.init(factory);
|
RedisProperties cfg = Binder.get(environment).bind(ALONE_PREFIX, RedisProperties.class).get();
|
||||||
return;
|
|
||||||
} catch (ClassNotFoundException e) {
|
// 1. Redis配置
|
||||||
|
RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
|
||||||
|
redisConfig.setHostName(cfg.getHost());
|
||||||
|
redisConfig.setPort(cfg.getPort());
|
||||||
|
redisConfig.setDatabase(cfg.getDatabase());
|
||||||
|
redisConfig.setPassword(RedisPassword.of(cfg.getPassword()));
|
||||||
|
|
||||||
|
// 2. 连接池配置
|
||||||
|
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
|
||||||
|
// pool配置
|
||||||
|
Lettuce lettuce = cfg.getLettuce();
|
||||||
|
if(lettuce.getPool() != null) {
|
||||||
|
RedisProperties.Pool pool = cfg.getLettuce().getPool();
|
||||||
|
// 连接池最大连接数
|
||||||
|
poolConfig.setMaxTotal(pool.getMaxActive());
|
||||||
|
// 连接池中的最大空闲连接
|
||||||
|
poolConfig.setMaxIdle(pool.getMaxIdle());
|
||||||
|
// 连接池中的最小空闲连接
|
||||||
|
poolConfig.setMinIdle(pool.getMinIdle());
|
||||||
|
// 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||||
|
poolConfig.setMaxWaitMillis(pool.getMaxWait().toMillis());
|
||||||
|
}
|
||||||
|
LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder();
|
||||||
|
// timeout
|
||||||
|
if(cfg.getTimeout() != null) {
|
||||||
|
builder.commandTimeout(cfg.getTimeout());
|
||||||
|
}
|
||||||
|
// shutdownTimeout
|
||||||
|
if(lettuce.getShutdownTimeout() != null) {
|
||||||
|
builder.shutdownTimeout(lettuce.getShutdownTimeout());
|
||||||
|
}
|
||||||
|
// 创建Factory对象
|
||||||
|
LettuceClientConfiguration clientConfig = builder.poolConfig(poolConfig).build();
|
||||||
|
LettuceConnectionFactory factory = new LettuceConnectionFactory(redisConfig, clientConfig);
|
||||||
|
factory.afterPropertiesSet();
|
||||||
|
|
||||||
|
// 3. 开始初始化 SaTokenDao
|
||||||
|
// 如果是SaTokenDaoRedis
|
||||||
|
try {
|
||||||
|
Class.forName("cn.dev33.satoken.dao.SaTokenDaoRedis");
|
||||||
|
SaTokenDaoRedis dao = (SaTokenDaoRedis)saTokenDao;
|
||||||
|
dao.isInit = false;
|
||||||
|
dao.init(factory);
|
||||||
|
return;
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
}
|
||||||
|
// 如果是SaTokenDaoRedisJackson
|
||||||
|
try {
|
||||||
|
Class.forName("cn.dev33.satoken.dao.SaTokenDaoRedisJackson");
|
||||||
|
SaTokenDaoRedisJackson dao = (SaTokenDaoRedisJackson)saTokenDao;
|
||||||
|
dao.isInit = false;
|
||||||
|
dao.init(factory);
|
||||||
|
return;
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user