mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-06-28 13:34:18 +08:00
Compare commits
119 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b0d42821d7 | ||
![]() |
ebc381772f | ||
![]() |
d08f93bdc0 | ||
![]() |
c2fc4decef | ||
![]() |
f7378f3898 | ||
![]() |
7bde74bc51 | ||
![]() |
5fc40a5af2 | ||
![]() |
e13b263f27 | ||
![]() |
bd22a94a10 | ||
![]() |
be5ee2fc2b | ||
![]() |
f4e7dac95f | ||
![]() |
e97cddb5e2 | ||
![]() |
e80369eb4b | ||
![]() |
0cd3d66712 | ||
![]() |
923b76a8db | ||
![]() |
a6b38430cd | ||
![]() |
e2c08f7dd2 | ||
![]() |
986111b10c | ||
![]() |
2cf18309b2 | ||
![]() |
d22ac1b7cf | ||
![]() |
fece7081a9 | ||
![]() |
dc874c2275 | ||
![]() |
5ab847c441 | ||
![]() |
f98db819ef | ||
![]() |
2b5840dcbb | ||
![]() |
9913a901aa | ||
![]() |
c22fb3efb1 | ||
![]() |
fee9ef1643 | ||
![]() |
6ce8f38aaf | ||
![]() |
760cac764b | ||
![]() |
edbd63f81b | ||
![]() |
a5ea1a3a4d | ||
![]() |
df91c2ece0 | ||
![]() |
9fcaf89412 | ||
![]() |
44c153fd19 | ||
![]() |
3edac001ce | ||
![]() |
3e13a39244 | ||
![]() |
5b3a64b9fc | ||
![]() |
0ed0c277df | ||
![]() |
f1089f697c | ||
![]() |
1304cb248d | ||
![]() |
04792f7290 | ||
![]() |
9f52c4d399 | ||
![]() |
c4e34704d5 | ||
![]() |
2523d4b8df | ||
![]() |
a3c7568fc3 | ||
![]() |
7c35e6a859 | ||
![]() |
a27e1d85b6 | ||
![]() |
49622fbf2d | ||
![]() |
5543905505 | ||
![]() |
6fc3b09581 | ||
![]() |
9dc6ade2cf | ||
![]() |
bb1702da0b | ||
![]() |
dc85fe660a | ||
![]() |
bef2ae7c84 | ||
![]() |
c70152962a | ||
![]() |
1c0831bd94 | ||
![]() |
1391b4981a | ||
![]() |
6da1359dcf | ||
![]() |
08fa9fe06a | ||
![]() |
cad172819a | ||
![]() |
d6187e8c34 | ||
![]() |
5d3b1f4455 | ||
![]() |
88f99c49fb | ||
![]() |
2ecd52b3be | ||
![]() |
bfc06c19cf | ||
![]() |
213d98d848 | ||
![]() |
b59fa26edf | ||
![]() |
c615e163cb | ||
![]() |
25e3a3f9cd | ||
![]() |
f6ec0fa465 | ||
![]() |
75eb78494b | ||
![]() |
f150209a4f | ||
![]() |
6f845fb6b8 | ||
![]() |
6e9bb2b31a | ||
![]() |
1d9b730685 | ||
![]() |
ad4e8408fe | ||
![]() |
62e5c9b19d | ||
![]() |
5aac119beb | ||
![]() |
c2dea166e4 | ||
![]() |
3cb81149c1 | ||
![]() |
72c91ff0aa | ||
![]() |
0229459d8d | ||
![]() |
66c431bb3e | ||
![]() |
9ceebda9f5 | ||
![]() |
95cc77a8bc | ||
![]() |
6ef777e58f | ||
![]() |
b53eac9269 | ||
![]() |
0ae51a1b56 | ||
![]() |
a17befcebb | ||
![]() |
abdfb2305d | ||
![]() |
84506d49f0 | ||
![]() |
8992b17f7d | ||
![]() |
476910dffb | ||
![]() |
79113c5848 | ||
![]() |
2d777fbd22 | ||
![]() |
b5dae2e6cc | ||
![]() |
35d8ff06ca | ||
![]() |
7e5c2e6fce | ||
![]() |
e6400a0cd5 | ||
![]() |
2102d2c1f2 | ||
![]() |
a92fb8eee2 | ||
![]() |
93566c58a4 | ||
![]() |
624d1645fa | ||
![]() |
3f86dfdc12 | ||
![]() |
d3719ab423 | ||
![]() |
4a8490c0c4 | ||
![]() |
3658779d87 | ||
![]() |
cc681672df | ||
![]() |
4d1040076b | ||
![]() |
86ca5c7fcb | ||
![]() |
757e1b86a7 | ||
![]() |
95f4d62c8e | ||
![]() |
f6a14d4241 | ||
![]() |
66d2fc6d1e | ||
![]() |
2ef879c75f | ||
![]() |
895941b5c8 | ||
![]() |
f2cc698ab8 | ||
![]() |
72e18bd906 |
22
README.md
22
README.md
@ -1,8 +1,8 @@
|
||||
<p align="center">
|
||||
<img alt="logo" src="https://sa-token.cc/logo.png" width="150" height="150">
|
||||
</p>
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">Sa-Token v1.42.0</h1>
|
||||
<h4 align="center">一个轻量级 Java 权限认证框架,让鉴权变得简单、优雅!</h4>
|
||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">Sa-Token v1.44.0</h1>
|
||||
<h4 align="center">开源、免费、轻量级 Java 权限认证框架,让鉴权变得简单、优雅!</h4>
|
||||
<p align="center">
|
||||
<a href="https://gitee.com/dromara/sa-token/stargazers"><img src="https://gitee.com/dromara/sa-token/badge/star.svg?theme=gvp"></a>
|
||||
<a href="https://gitee.com/dromara/sa-token/members"><img src="https://gitee.com/dromara/sa-token/badge/fork.svg?theme=gvp"></a>
|
||||
@ -23,6 +23,8 @@
|
||||
|
||||
Sa-Token 是一个轻量级 Java 权限认证框架,目前拥有五大核心模块:登录认证、权限认证、单点登录、OAuth2.0、微服务鉴权。
|
||||
|
||||

|
||||
|
||||
要在 SpringBoot 项目中使用 Sa-Token,你只需要在 pom.xml 中引入依赖:
|
||||
|
||||
``` xml
|
||||
@ -30,7 +32,7 @@ Sa-Token 是一个轻量级 Java 权限认证框架,目前拥有五大核心
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot-starter</artifactId>
|
||||
<version>1.42.0</version>
|
||||
<version>1.44.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
@ -38,7 +40,7 @@ Sa-Token 是一个轻量级 Java 权限认证框架,目前拥有五大核心
|
||||
|
||||
|
||||
<details>
|
||||
<summary><b>简单示例展示:(点击展开 / 折叠)</b></summary>
|
||||
<summary><b>简单示例展示:</b>(点击展开 / 折叠)</summary>
|
||||
|
||||
Sa-Token 旨在以简单、优雅的方式完成系统的权限认证部分,以登录认证为例,你只需要:
|
||||
|
||||
@ -90,13 +92,15 @@ registry.addInterceptor(new SaInterceptor(handler -> {
|
||||
})).addPathPatterns("/**");
|
||||
```
|
||||
|
||||
当你受够 Shiro、SpringSecurity 等框架的三拜九叩之后,你就会明白,相对于这些传统老牌框架,Sa-Token 的 API 设计是多么的简单、优雅!
|
||||
**如果您曾经使用过 Shiro、SpringSecurity,在切换到 Sa-Token 后,您将体会到质的飞跃。**
|
||||
|
||||
<!-- 当你受够 Shiro、SpringSecurity 等框架的三拜九叩之后,你就会明白,相对于这些传统老牌框架,Sa-Token 的 API 设计是多么的简单、优雅! -->
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary> <b>核心模块一览:(点击展开 / 折叠)</b> </summary>
|
||||
<summary> <b>核心模块一览:</b>(点击展开 / 折叠) </summary>
|
||||
|
||||
- **登录认证** —— 单端登录、多端登录、同端互斥登录、七天内免登录。
|
||||
- **权限认证** —— 权限认证、角色认证、会话二级认证。
|
||||
@ -139,12 +143,13 @@ registry.addInterceptor(new SaInterceptor(handler -> {
|
||||
</details>
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
### SSO 单点登录
|
||||
|
||||
Sa-Token SSO 分为三种模式,解决同域、跨域、共享Redis、跨Redis、前后端一体、前后端分离……等不同架构下的 SSO 接入问题:
|
||||
|
||||

|
||||
|
||||
| 系统架构 | 采用模式 | 简介 | 文档链接 |
|
||||
| :-------- | :-------- | :-------- | :-------- |
|
||||
| 前端同域 + 后端同 Redis | 模式一 | 共享Cookie同步会话 | [文档](https://sa-token.cc/doc.html#/sso/sso-type1)、[示例](https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-sso1-client) |
|
||||
@ -193,6 +198,7 @@ Sa-Token-OAuth2 模块分为四种授权模式,解决不同场景下的授权
|
||||
|
||||
### 友情链接
|
||||
- [[ OkHttps ]](https://gitee.com/ejlchina-zhxu/okhttps):轻量级 http 通信框架,API无比优雅,支持 WebSocket、Stomp 协议
|
||||
- [[ Forest ]](https://gitee.com/dromara/forest):声明式与编程式双修,让天下没有难以发送的 HTTP 请求
|
||||
- [[ Bean Searcher ]](https://github.com/ejlchina/bean-searcher):专注高级查询的只读 ORM,使一行代码实现复杂列表检索!
|
||||
- [[ Jpom ]](https://gitee.com/dromara/Jpom):简而轻的低侵入式在线构建、自动部署、日常运维、项目监控软件。
|
||||
- [[ TLog ]](https://gitee.com/dromara/TLog):一个轻量级的分布式日志标记追踪神器。
|
||||
|
@ -27,6 +27,7 @@ cd sa-token-demo-springboot3-redis & call mvn clean & cd ..
|
||||
cd sa-token-demo-springboot-low-version & call mvn clean & cd ..
|
||||
cd sa-token-demo-springboot-redis & call mvn clean & cd ..
|
||||
cd sa-token-demo-springboot-redisson & call mvn clean & cd ..
|
||||
cd sa-token-demo-sse & call mvn clean & cd ..
|
||||
cd sa-token-demo-ssm & call mvn clean & cd ..
|
||||
cd sa-token-demo-test & call mvn clean & cd ..
|
||||
cd sa-token-demo-thymeleaf & call mvn clean & cd ..
|
||||
@ -57,8 +58,9 @@ cd sa-token-demo-sso-server & call mvn clean & cd ..
|
||||
cd sa-token-demo-sso1-client & call mvn clean & cd ..
|
||||
cd sa-token-demo-sso2-client & call mvn clean & cd ..
|
||||
cd sa-token-demo-sso3-client & call mvn clean & cd ..
|
||||
cd sa-token-demo-sso3-client-test2 & call mvn clean & cd ..
|
||||
cd sa-token-demo-sso3-client-nosdk & call mvn clean & cd ..
|
||||
cd sa-token-demo-sso3-client-resdk & call mvn clean & cd ..
|
||||
cd sa-token-demo-sso3-client-anon & call mvn clean & cd ..
|
||||
cd ..
|
||||
|
||||
cd sa-token-demo-sso-for-solon
|
||||
|
19
pom.xml
19
pom.xml
@ -37,7 +37,7 @@
|
||||
|
||||
<!-- 一些属性 -->
|
||||
<properties>
|
||||
<revision>1.42.0</revision>
|
||||
<revision>1.44.0</revision>
|
||||
<jdk.version>1.8</jdk.version>
|
||||
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>utf-8</project.reporting.outputEncoding>
|
||||
@ -104,8 +104,23 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.3</version>
|
||||
<version>3.4.1</version>
|
||||
<configuration>
|
||||
<!-- 统一生成聚合文档,解决 mvn package 时控制台发出 javadoc 警告的问题 -->
|
||||
<aggregate>true</aggregate>
|
||||
<!-- 忽略部分 error 和 warning -->
|
||||
<failOnError>false</failOnError>
|
||||
<failOnWarnings>false</failOnWarnings>
|
||||
<additionalOptions>-Xdoclint:none</additionalOptions>
|
||||
<detectLinks>false</detectLinks>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>aggregate</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
|
@ -13,7 +13,7 @@
|
||||
<url>https://github.com/dromara/sa-token</url>
|
||||
|
||||
<properties>
|
||||
<revision>1.42.0</revision>
|
||||
<revision>1.44.0</revision>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@ -139,6 +139,16 @@
|
||||
<artifactId>sa-token-redis-jackson</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-forest</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-okhttps</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-redisson-spring-boot-starter</artifactId>
|
||||
@ -179,6 +189,16 @@
|
||||
<artifactId>sa-token-oauth2</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-apikey</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-sign</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-quick-login</artifactId>
|
||||
|
@ -15,9 +15,6 @@
|
||||
*/
|
||||
package cn.dev33.satoken;
|
||||
|
||||
import cn.dev33.satoken.apikey.SaApiKeyTemplate;
|
||||
import cn.dev33.satoken.apikey.loader.SaApiKeyDataLoader;
|
||||
import cn.dev33.satoken.apikey.loader.SaApiKeyDataLoaderDefaultImpl;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.config.SaTokenConfigFactory;
|
||||
import cn.dev33.satoken.context.SaTokenContext;
|
||||
@ -26,6 +23,8 @@ import cn.dev33.satoken.dao.SaTokenDao;
|
||||
import cn.dev33.satoken.dao.SaTokenDaoDefaultImpl;
|
||||
import cn.dev33.satoken.error.SaErrorCode;
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.http.SaHttpTemplate;
|
||||
import cn.dev33.satoken.http.SaHttpTemplateDefaultImpl;
|
||||
import cn.dev33.satoken.json.SaJsonTemplate;
|
||||
import cn.dev33.satoken.json.SaJsonTemplateDefaultImpl;
|
||||
import cn.dev33.satoken.listener.SaTokenEventCenter;
|
||||
@ -35,7 +34,6 @@ import cn.dev33.satoken.same.SaSameTemplate;
|
||||
import cn.dev33.satoken.secure.totp.SaTotpTemplate;
|
||||
import cn.dev33.satoken.serializer.SaSerializerTemplate;
|
||||
import cn.dev33.satoken.serializer.impl.SaSerializerTemplateForJson;
|
||||
import cn.dev33.satoken.sign.SaSignTemplate;
|
||||
import cn.dev33.satoken.stp.StpInterface;
|
||||
import cn.dev33.satoken.stp.StpInterfaceDefaultImpl;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
@ -201,6 +199,25 @@ public class SaManager {
|
||||
return saJsonTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP 转换器
|
||||
*/
|
||||
private volatile static SaHttpTemplate saHttpTemplate;
|
||||
public static void setSaHttpTemplate(SaHttpTemplate saHttpTemplate) {
|
||||
SaManager.saHttpTemplate = saHttpTemplate;
|
||||
SaTokenEventCenter.doRegisterComponent("SaHttpTemplate", saHttpTemplate);
|
||||
}
|
||||
public static SaHttpTemplate getSaHttpTemplate() {
|
||||
if (saHttpTemplate == null) {
|
||||
synchronized (SaManager.class) {
|
||||
if (saHttpTemplate == null) {
|
||||
SaManager.saHttpTemplate = new SaHttpTemplateDefaultImpl();
|
||||
}
|
||||
}
|
||||
}
|
||||
return saHttpTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化器
|
||||
*/
|
||||
@ -220,25 +237,6 @@ public class SaManager {
|
||||
return saSerializerTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* API 参数签名
|
||||
*/
|
||||
private volatile static SaSignTemplate saSignTemplate;
|
||||
public static void setSaSignTemplate(SaSignTemplate saSignTemplate) {
|
||||
SaManager.saSignTemplate = saSignTemplate;
|
||||
SaTokenEventCenter.doRegisterComponent("SaSignTemplate", saSignTemplate);
|
||||
}
|
||||
public static SaSignTemplate getSaSignTemplate() {
|
||||
if (saSignTemplate == null) {
|
||||
synchronized (SaManager.class) {
|
||||
if (saSignTemplate == null) {
|
||||
SaManager.saSignTemplate = new SaSignTemplate();
|
||||
}
|
||||
}
|
||||
}
|
||||
return saSignTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same-Token 同源系统认证模块
|
||||
*/
|
||||
@ -289,44 +287,6 @@ public class SaManager {
|
||||
return totpTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* ApiKey 数据加载器
|
||||
*/
|
||||
private volatile static SaApiKeyDataLoader apiKeyDataLoader;
|
||||
public static void setSaApiKeyDataLoader(SaApiKeyDataLoader apiKeyDataLoader) {
|
||||
SaManager.apiKeyDataLoader = apiKeyDataLoader;
|
||||
SaTokenEventCenter.doRegisterComponent("SaApiKeyDataLoader", apiKeyDataLoader);
|
||||
}
|
||||
public static SaApiKeyDataLoader getSaApiKeyDataLoader() {
|
||||
if (apiKeyDataLoader == null) {
|
||||
synchronized (SaManager.class) {
|
||||
if (apiKeyDataLoader == null) {
|
||||
SaManager.apiKeyDataLoader = new SaApiKeyDataLoaderDefaultImpl();
|
||||
}
|
||||
}
|
||||
}
|
||||
return apiKeyDataLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* ApiKey 操作类
|
||||
*/
|
||||
private volatile static SaApiKeyTemplate apiKeyTemplate;
|
||||
public static void setSaApiKeyTemplate(SaApiKeyTemplate apiKeyTemplate) {
|
||||
SaManager.apiKeyTemplate = apiKeyTemplate;
|
||||
SaTokenEventCenter.doRegisterComponent("SaApiKeyTemplate", apiKeyTemplate);
|
||||
}
|
||||
public static SaApiKeyTemplate getSaApiKeyTemplate() {
|
||||
if (apiKeyTemplate == null) {
|
||||
synchronized (SaManager.class) {
|
||||
if (apiKeyTemplate == null) {
|
||||
SaManager.apiKeyTemplate = new SaApiKeyTemplate();
|
||||
}
|
||||
}
|
||||
}
|
||||
return apiKeyTemplate;
|
||||
}
|
||||
|
||||
|
||||
// ------------------- StpLogic 相关 -------------------
|
||||
|
||||
|
@ -15,10 +15,7 @@
|
||||
*/
|
||||
package cn.dev33.satoken.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 批量注解鉴权:只要满足其中一个注解即可通过验证
|
||||
@ -81,4 +78,11 @@ public @interface SaCheckOr {
|
||||
*/
|
||||
SaCheckDisable[] disable() default {};
|
||||
|
||||
/**
|
||||
* 需要追加抓取的注解 Class (只能填写 Sa-Token 相关注解类型)
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
Class<? extends Annotation>[] append() default {};
|
||||
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
package cn.dev33.satoken.annotation.handler;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 所有注解处理器的父接口
|
||||
@ -35,18 +35,18 @@ public interface SaAnnotationHandlerInterface<T extends Annotation> {
|
||||
/**
|
||||
* 所需要执行的校验方法
|
||||
* @param at 注解对象
|
||||
* @param method 被标注的注解的方法引用
|
||||
* @param element 被标注的注解的元素(方法/类)引用
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default void check(Annotation at, Method method) {
|
||||
checkMethod((T) at, method);
|
||||
default void check(Annotation at, AnnotatedElement element) {
|
||||
checkMethod((T) at, element);
|
||||
}
|
||||
|
||||
/**
|
||||
* 所需要执行的校验方法(转换类型后)
|
||||
* @param at 注解对象
|
||||
* @param method 被标注的注解的方法引用
|
||||
* @param element 被标注的注解的元素(方法/类)引用
|
||||
*/
|
||||
void checkMethod(T at, Method method);
|
||||
void checkMethod(T at, AnnotatedElement element);
|
||||
|
||||
}
|
@ -19,7 +19,7 @@ import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.annotation.SaCheckDisable;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckDisable 的处理器
|
||||
@ -35,7 +35,7 @@ public class SaCheckDisableHandler implements SaAnnotationHandlerInterface<SaChe
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckDisable at, Method method) {
|
||||
public void checkMethod(SaCheckDisable at, AnnotatedElement element) {
|
||||
_checkMethod(at.type(), at.value(), at.level());
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ package cn.dev33.satoken.annotation.handler;
|
||||
import cn.dev33.satoken.annotation.SaCheckHttpBasic;
|
||||
import cn.dev33.satoken.httpauth.basic.SaHttpBasicUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckHttpBasic 的处理器
|
||||
@ -34,7 +34,7 @@ public class SaCheckHttpBasicHandler implements SaAnnotationHandlerInterface<SaC
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckHttpBasic at, Method method) {
|
||||
public void checkMethod(SaCheckHttpBasic at, AnnotatedElement element) {
|
||||
_checkMethod(at.realm(), at.account());
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.httpauth.digest.SaHttpDigestUtil;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckHttpDigest 的处理器
|
||||
@ -36,7 +36,7 @@ public class SaCheckHttpDigestHandler implements SaAnnotationHandlerInterface<Sa
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckHttpDigest at, Method method) {
|
||||
public void checkMethod(SaCheckHttpDigest at, AnnotatedElement element) {
|
||||
_checkMethod(at.username(), at.password(), at.realm(), at.value());
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckLogin 的处理器
|
||||
@ -35,7 +35,7 @@ public class SaCheckLoginHandler implements SaAnnotationHandlerInterface<SaCheck
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckLogin at, Method method) {
|
||||
public void checkMethod(SaCheckLogin at, AnnotatedElement element) {
|
||||
_checkMethod(at.type());
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@ -39,8 +39,8 @@ public class SaCheckOrHandler implements SaAnnotationHandlerInterface<SaCheckOr>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckOr at, Method method) {
|
||||
_checkMethod(at.login(), at.role(), at.permission(), at.safe(), at.httpBasic(), at.httpDigest(), at.disable(), method);
|
||||
public void checkMethod(SaCheckOr at, AnnotatedElement element) {
|
||||
_checkMethod(at.login(), at.role(), at.permission(), at.safe(), at.httpBasic(), at.httpDigest(), at.disable(), at.append(), element);
|
||||
}
|
||||
|
||||
public static void _checkMethod(
|
||||
@ -51,7 +51,8 @@ public class SaCheckOrHandler implements SaAnnotationHandlerInterface<SaCheckOr>
|
||||
SaCheckHttpBasic[] httpBasic,
|
||||
SaCheckHttpDigest[] httpDigest,
|
||||
SaCheckDisable[] disable,
|
||||
Method method
|
||||
Class<? extends Annotation>[] append,
|
||||
AnnotatedElement element
|
||||
) {
|
||||
// 先把所有注解塞到一个 list 里
|
||||
List<Annotation> annotationList = new ArrayList<>();
|
||||
@ -62,6 +63,12 @@ public class SaCheckOrHandler implements SaAnnotationHandlerInterface<SaCheckOr>
|
||||
annotationList.addAll(Arrays.asList(disable));
|
||||
annotationList.addAll(Arrays.asList(httpBasic));
|
||||
annotationList.addAll(Arrays.asList(httpDigest));
|
||||
for (Class<? extends Annotation> annotationClass : append) {
|
||||
Annotation annotation = SaAnnotationStrategy.instance.getAnnotation.apply(element, annotationClass);
|
||||
if(annotation != null) {
|
||||
annotationList.add(annotation);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果 atList 为空,说明 SaCheckOr 上不包含任何注解校验,我们直接跳过即可
|
||||
if(annotationList.isEmpty()) {
|
||||
@ -72,7 +79,7 @@ public class SaCheckOrHandler implements SaAnnotationHandlerInterface<SaCheckOr>
|
||||
List<SaTokenException> errorList = new ArrayList<>();
|
||||
for (Annotation item : annotationList) {
|
||||
try {
|
||||
SaAnnotationStrategy.instance.annotationHandlerMap.get(item.annotationType()).check(item, method);
|
||||
SaAnnotationStrategy.instance.annotationHandlerMap.get(item.annotationType()).check(item, element);
|
||||
// 只要有一个校验通过,就可以直接返回了
|
||||
return;
|
||||
} catch (SaTokenException e) {
|
||||
|
@ -22,7 +22,7 @@ import cn.dev33.satoken.exception.NotPermissionException;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckPermission 的处理器
|
||||
@ -38,7 +38,7 @@ public class SaCheckPermissionHandler implements SaAnnotationHandlerInterface<Sa
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckPermission at, Method method) {
|
||||
public void checkMethod(SaCheckPermission at, AnnotatedElement element) {
|
||||
_checkMethod(at.type(), at.value(), at.mode(), at.orRole());
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ import cn.dev33.satoken.annotation.SaCheckRole;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckRole 的处理器
|
||||
@ -36,7 +36,7 @@ public class SaCheckRoleHandler implements SaAnnotationHandlerInterface<SaCheckR
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckRole at, Method method) {
|
||||
public void checkMethod(SaCheckRole at, AnnotatedElement element) {
|
||||
_checkMethod(at.type(), at.value(), at.mode());
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.annotation.SaCheckSafe;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaCheckSafe 的处理器
|
||||
@ -35,7 +35,7 @@ public class SaCheckSafeHandler implements SaAnnotationHandlerInterface<SaCheckS
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaCheckSafe at, Method method) {
|
||||
public void checkMethod(SaCheckSafe at, AnnotatedElement element) {
|
||||
_checkMethod(at.type(), at.value());
|
||||
}
|
||||
|
||||
|
@ -18,10 +18,11 @@ package cn.dev33.satoken.annotation.handler;
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.dev33.satoken.router.SaRouter;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaIgnore 的处理器
|
||||
* <h2> v1.43.0 版本起,SaIgnore 注解处理逻辑已转移到全局策略中,此处理器代码仅做留档 </h2>
|
||||
*
|
||||
* @author click33
|
||||
* @since 2024/8/2
|
||||
@ -34,7 +35,7 @@ public class SaIgnoreHandler implements SaAnnotationHandlerInterface<SaIgnore> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaIgnore at, Method method) {
|
||||
public void checkMethod(SaIgnore at, AnnotatedElement element) {
|
||||
_checkMethod();
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,6 @@ import cn.dev33.satoken.stp.parameter.enums.SaReplacedRange;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Sa-Token 配置类 Model
|
||||
@ -223,21 +221,6 @@ public class SaTokenConfig implements Serializable {
|
||||
*/
|
||||
public SaCookieConfig cookie = new SaCookieConfig();
|
||||
|
||||
/**
|
||||
* API 签名配置对象
|
||||
*/
|
||||
public SaSignConfig sign = new SaSignConfig();
|
||||
|
||||
/**
|
||||
* API 签名配置 多实例
|
||||
*/
|
||||
public Map<String, SaSignConfig> signMany = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* API Key 相关配置
|
||||
*/
|
||||
public SaApiKeyConfig apiKey = new SaApiKeyConfig();
|
||||
|
||||
/**
|
||||
* @return token 名称 (同时也是: cookie 名称、提交 token 时参数的名称、存储 token 时的 key 前缀)
|
||||
*/
|
||||
@ -866,62 +849,6 @@ public class SaTokenConfig implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return API 签名全局配置对象
|
||||
*/
|
||||
public SaSignConfig getSign() {
|
||||
return sign;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sign API 签名全局配置对象
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaTokenConfig setSign(SaSignConfig sign) {
|
||||
this.sign = sign;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 API 签名配置 多实例
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public Map<String, SaSignConfig> getSignMany() {
|
||||
return this.signMany;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 API 签名配置 多实例
|
||||
*
|
||||
* @param signMany /
|
||||
* @return /
|
||||
*/
|
||||
public SaTokenConfig setSignMany(Map<String, SaSignConfig> signMany) {
|
||||
this.signMany = signMany;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* API Key 相关配置
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public SaApiKeyConfig getApiKey() {
|
||||
return this.apiKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 API Key 相关配置
|
||||
*
|
||||
* @param apiKey /
|
||||
* @return /
|
||||
*/
|
||||
public SaTokenConfig setApiKey(SaApiKeyConfig apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@ -963,9 +890,6 @@ public class SaTokenConfig implements Serializable {
|
||||
+ ", sameTokenTimeout=" + sameTokenTimeout
|
||||
+ ", checkSameToken=" + checkSameToken
|
||||
+ ", cookie=" + cookie
|
||||
+ ", sign=" + sign
|
||||
+ ", signMany=" + signMany
|
||||
+ ", apiKey=" + apiKey
|
||||
+ "]";
|
||||
}
|
||||
|
||||
@ -980,7 +904,7 @@ public class SaTokenConfig implements Serializable {
|
||||
*/
|
||||
@Deprecated
|
||||
public long getActivityTimeout() {
|
||||
System.err.println("配置项已过期,请更换:sa-token.activity-timeout -> sa-token.active-timeout");
|
||||
// System.err.println("配置项已过期,请更换:sa-token.activity-timeout -> sa-token.active-timeout");
|
||||
return activeTimeout;
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ public interface SaRequest {
|
||||
* @return /
|
||||
*/
|
||||
default boolean isAjax() {
|
||||
return getHeader("X-Requested-With") != null;
|
||||
return "XMLHttpRequest".equalsIgnoreCase(getHeader("X-Requested-With")) || isParam("_ajax", "true");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -37,6 +37,9 @@ public interface SaErrorCode {
|
||||
/** JSON 转换器未实现 */
|
||||
int CODE_10003 = 10003;
|
||||
|
||||
/** HTTP 请求处理器未实现 */
|
||||
int CODE_10004 = 10004;
|
||||
|
||||
/** 未能从全局 StpLogic 集合中找到对应 type 的 StpLogic */
|
||||
int CODE_10011 = 10011;
|
||||
|
||||
@ -190,42 +193,6 @@ public interface SaErrorCode {
|
||||
/** RSA 私钥解密异常 */
|
||||
int CODE_12119 = 12119;
|
||||
|
||||
// ------------
|
||||
|
||||
/** 参与参数签名的秘钥不可为空 */
|
||||
int CODE_12201 = 12201;
|
||||
|
||||
/** 给定的签名无效 */
|
||||
int CODE_12202 = 12202;
|
||||
|
||||
/** timestamp 超出允许的范围 */
|
||||
int CODE_12203 = 12203;
|
||||
|
||||
/** 未找到对应 appid 的 SaSignConfig */
|
||||
int CODE_12211 = 12211;
|
||||
|
||||
// ------------
|
||||
|
||||
/** 无效 API Key */
|
||||
int CODE_12301 = 12301;
|
||||
|
||||
/** API Key 已过期 */
|
||||
int CODE_12302 = 12302;
|
||||
|
||||
/** API Key 已被禁用 */
|
||||
int CODE_12303 = 12303;
|
||||
|
||||
/** API Key 字段自检未通过 */
|
||||
int CODE_12304 = 12304;
|
||||
|
||||
/** 未开启索引记录功能却调用了相关 API */
|
||||
int CODE_12305 = 12305;
|
||||
|
||||
/** API Key 不具有指定 Scope */
|
||||
int CODE_12311 = 12311;
|
||||
|
||||
/** API Key 不属于指定用户 */
|
||||
int CODE_12312 = 12312;
|
||||
|
||||
// ------------
|
||||
|
||||
|
@ -148,36 +148,4 @@ public class SaTokenException extends RuntimeException {
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------- 已过期 -------------------
|
||||
|
||||
/**
|
||||
* 如果flag==true,则抛出message异常
|
||||
* <h2>已过期:请使用 notTrue 代替,用法不变</h2>
|
||||
*
|
||||
* @param flag 标记
|
||||
* @param message 异常信息
|
||||
* @param code 异常细分状态码
|
||||
*/
|
||||
@Deprecated
|
||||
public static void throwBy(boolean flag, String message, int code) {
|
||||
if(flag) {
|
||||
throw new SaTokenException(message).setCode(code);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果value==null或者isEmpty,则抛出message异常
|
||||
* <h2>已过期:请使用 notEmpty 代替,用法不变</h2>
|
||||
*
|
||||
* @param value 值
|
||||
* @param message 异常信息
|
||||
* @param code 异常细分状态码
|
||||
*/
|
||||
@Deprecated
|
||||
public static void throwByNull(Object value, String message, int code) {
|
||||
if(SaFoxUtil.isEmpty(value)) {
|
||||
throw new SaTokenException(message).setCode(code);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.http;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Http 请求处理器
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.43.0
|
||||
*/
|
||||
public interface SaHttpTemplate {
|
||||
|
||||
/**
|
||||
* get 请求
|
||||
*
|
||||
* @param url /
|
||||
* @return /
|
||||
*/
|
||||
String get(String url);
|
||||
|
||||
/**
|
||||
* post 请求,form-data 格式参数
|
||||
*
|
||||
* @param url /
|
||||
* @param params /
|
||||
* @return /
|
||||
*/
|
||||
String postByFormData(String url, Map<String, Object> params);
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.http;
|
||||
|
||||
import cn.dev33.satoken.error.SaErrorCode;
|
||||
import cn.dev33.satoken.exception.NotImplException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Http 请求处理器,默认实现类
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.43.0
|
||||
*/
|
||||
public class SaHttpTemplateDefaultImpl implements SaHttpTemplate {
|
||||
|
||||
public static final String ERROR_MESSAGE = "HTTP 请求处理器未实现";
|
||||
|
||||
/**
|
||||
* get 请求
|
||||
*
|
||||
* @param url /
|
||||
* @return /
|
||||
*/
|
||||
@Override
|
||||
public String get(String url) {
|
||||
throw new NotImplException(ERROR_MESSAGE).setCode(SaErrorCode.CODE_10004);
|
||||
}
|
||||
|
||||
/**
|
||||
* post 请求,form-data 格式参数
|
||||
*/
|
||||
@Override
|
||||
public String postByFormData(String url, Map<String, Object> params) {
|
||||
throw new NotImplException(ERROR_MESSAGE).setCode(SaErrorCode.CODE_10004);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.http;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Http 请求处理器 工具类
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.43.0
|
||||
*/
|
||||
public class SaHttpUtil {
|
||||
|
||||
/**
|
||||
* get 请求
|
||||
*
|
||||
* @param url /
|
||||
* @return /
|
||||
*/
|
||||
public static String get(String url) {
|
||||
return SaManager.getSaHttpTemplate().get(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* post 请求,form-data 格式参数
|
||||
*
|
||||
* @param url /
|
||||
* @param params /
|
||||
* @return /
|
||||
*/
|
||||
public static String postByFormData(String url, Map<String, Object> params) {
|
||||
return SaManager.getSaHttpTemplate().postByFormData(url, params);
|
||||
}
|
||||
|
||||
}
|
@ -121,6 +121,11 @@ public class SaHttpDigestTemplate {
|
||||
if (kv.length == 2) {
|
||||
map.put(kv[0].trim(), kv[1].trim().replace("\"", ""));
|
||||
}
|
||||
// 兼容字符串包含多个=的情况,如:uri 带参数的问题
|
||||
// username="sa", realm="Sa-Token", nonce="IWlEwO23oCAbIAbHX1BYnX5ddKHUdsjW", uri="/test/testDigest?name=zhangsan&age=18", response="c4359210ccb23c985234ee6e02def88d", opaque="H6jPyjwfioc0oUbDE0OSmpX7wznfxxMo", qop=auth, nc=00000002, cnonce="46dd0073c981a9c7"
|
||||
else if (s.contains("=")) {
|
||||
map.put(kv[0].trim(), s.substring(kv[0].length() + 1).trim().replace("\"", ""));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -265,15 +265,16 @@ public class SaTokenEventCenter {
|
||||
}
|
||||
|
||||
/**
|
||||
* 事件发布:指定 Token 续期成功
|
||||
*
|
||||
* @param tokenValue token 值
|
||||
* @param loginId 账号id
|
||||
* @param timeout 续期时间
|
||||
* 每次 Token 续期时触发(注意:是 timeout 续期,而不是 active-timeout 续期)
|
||||
*
|
||||
* @param loginType 账号类别
|
||||
* @param loginId 账号id
|
||||
* @param tokenValue token 值
|
||||
* @param timeout 续期时间
|
||||
*/
|
||||
public static void doRenewTimeout(String tokenValue, Object loginId, long timeout) {
|
||||
public static void doRenewTimeout(String loginType, Object loginId, String tokenValue, long timeout) {
|
||||
for (SaTokenListener listener : listenerList) {
|
||||
listener.doRenewTimeout(tokenValue, loginId, timeout);
|
||||
listener.doRenewTimeout(loginType, loginId, tokenValue, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,12 +112,13 @@ public interface SaTokenListener {
|
||||
|
||||
/**
|
||||
* 每次 Token 续期时触发(注意:是 timeout 续期,而不是 active-timeout 续期)
|
||||
*
|
||||
* @param tokenValue token 值
|
||||
* @param loginId 账号id
|
||||
*
|
||||
* @param loginType 账号类别
|
||||
* @param loginId 账号id
|
||||
* @param tokenValue token 值
|
||||
* @param timeout 续期时间
|
||||
*/
|
||||
void doRenewTimeout(String tokenValue, Object loginId, long timeout);
|
||||
void doRenewTimeout(String loginType, Object loginId, String tokenValue, long timeout);
|
||||
|
||||
/**
|
||||
* 全局组件载入
|
||||
|
@ -17,8 +17,8 @@ package cn.dev33.satoken.listener;
|
||||
|
||||
import cn.dev33.satoken.annotation.handler.SaAnnotationHandlerInterface;
|
||||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
|
||||
import static cn.dev33.satoken.SaManager.log;
|
||||
@ -112,14 +112,13 @@ public class SaTokenListenerForLog implements SaTokenListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* 每次Token续期时触发
|
||||
* 每次 Token 续期时触发
|
||||
*/
|
||||
@Override
|
||||
public void doRenewTimeout(String tokenValue, Object loginId, long timeout) {
|
||||
public void doRenewTimeout(String loginType, Object loginId, String tokenValue, long timeout) {
|
||||
log.info("token 续期成功, {} 秒后到期, 帐号={}, token值={} ", timeout, loginId, tokenValue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 全局组件载入
|
||||
* @param compName 组件名称
|
||||
|
@ -78,7 +78,7 @@ public class SaTokenListenerForSimple implements SaTokenListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRenewTimeout(String tokenValue, Object loginId, long timeout) {
|
||||
public void doRenewTimeout(String loginType, Object loginId, String tokenValue, long timeout) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -151,6 +151,18 @@ public class SaTotpTemplate {
|
||||
return StrFormatter.format("otpauth://totp/{}?secret={}", account, secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成谷歌认证器的扫码字符串 (形如:otpauth://totp/{issuer}:{account}?secret={secretKey}&issuer={issuer})
|
||||
*
|
||||
* @param account 账户名
|
||||
* @param issuer 签发者
|
||||
* @param secretKey TOTP 秘钥
|
||||
* @return /
|
||||
*/
|
||||
public String generateGoogleSecretKey(String account, String issuer, String secretKey) {
|
||||
return StrFormatter.format("otpauth://totp/{}:{}?secret={}&issuer={}", issuer, account, secretKey, issuer);
|
||||
}
|
||||
|
||||
protected String _generateTOTP(String secretKey, long time) {
|
||||
// Base32解码密钥
|
||||
byte[] keyBytes = SaBase32Util.decodeStringToBytes(secretKey);
|
||||
|
@ -88,4 +88,16 @@ public class SaTotpUtil {
|
||||
return SaManager.getSaTotpTemplate().generateGoogleSecretKey(account, secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成谷歌认证器的扫码字符串 (形如:otpauth://totp/{issuer}:{account}?secret={secretKey}&issuer={issuer})
|
||||
*
|
||||
* @param account 账户名
|
||||
* @param issuer 签发者
|
||||
* @param secretKey TOTP 秘钥
|
||||
* @return /
|
||||
*/
|
||||
public static String generateGoogleSecretKey(String account, String issuer, String secretKey) {
|
||||
return SaManager.getSaTotpTemplate().generateGoogleSecretKey(account, issuer, secretKey);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -916,8 +916,16 @@ public class StpLogic {
|
||||
if(session != null) {
|
||||
|
||||
// 2、遍历此 SaTerminalInfo 客户端列表,清除相关数据
|
||||
List<SaTerminalInfo> terminalList = session.getTerminalListByDeviceType(logoutParameter.getDeviceType());
|
||||
List<SaTerminalInfo> terminalList = session.terminalListCopy();
|
||||
for (SaTerminalInfo terminal: terminalList) {
|
||||
// 不符合 deviceType 的跳过
|
||||
if( ! SaFoxUtil.isEmpty(logoutParameter.getDeviceType()) && ! logoutParameter.getDeviceType().equals(terminal.getDeviceType())) {
|
||||
continue;
|
||||
}
|
||||
// 不符合 deviceId 的跳过
|
||||
if( ! SaFoxUtil.isEmpty(logoutParameter.getDeviceId()) && ! logoutParameter.getDeviceId().equals(terminal.getDeviceId())) {
|
||||
continue;
|
||||
}
|
||||
_removeTerminal(session, terminal, logoutParameter);
|
||||
}
|
||||
|
||||
@ -1994,7 +2002,7 @@ public class StpLogic {
|
||||
}
|
||||
|
||||
// 7、$$ 发布事件:某某 token 被续期了
|
||||
SaTokenEventCenter.doRenewTimeout(tokenValue, loginId, timeout);
|
||||
SaTokenEventCenter.doRenewTimeout(loginType, loginId, tokenValue, timeout);
|
||||
}
|
||||
|
||||
|
||||
@ -2380,6 +2388,56 @@ public class StpLogic {
|
||||
session.forEachTerminalList(function);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前 token 指向的 SaTerminalInfo 设备信息,如果 token 无效则返回 null
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public SaTerminalInfo getTerminalInfo() {
|
||||
return getTerminalInfoByToken(getTokenValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回指定 token 指向的 SaTerminalInfo 设备信息,如果 Token 无效则返回 null
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
* @return /
|
||||
*/
|
||||
public SaTerminalInfo getTerminalInfoByToken(String tokenValue) {
|
||||
// 1、如果 token 为 null,直接提前返回
|
||||
if(SaFoxUtil.isEmpty(tokenValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2、判断 Token 是否有效
|
||||
Object loginId = getLoginIdNotHandle(tokenValue);
|
||||
if( ! isValidLoginId(loginId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 3、判断 Account-Session 是否存在
|
||||
SaSession session = getSessionByLoginId(loginId, false);
|
||||
if(session == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 4、判断 Token 是否已被冻结
|
||||
if(isFreeze(tokenValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 5、遍历 Account-Session 上的客户端 token 列表,寻找当前 token 对应的设备类型
|
||||
List<SaTerminalInfo> terminalList = session.terminalListCopy();
|
||||
for (SaTerminalInfo terminal : terminalList) {
|
||||
if(terminal.getTokenValue().equals(tokenValue)) {
|
||||
return terminal;
|
||||
}
|
||||
}
|
||||
|
||||
// 6、没有找到,还是返回 null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前会话的登录设备类型
|
||||
*
|
||||
@ -2396,38 +2454,28 @@ public class StpLogic {
|
||||
* @return 当前令牌的登录设备类型
|
||||
*/
|
||||
public String getLoginDeviceTypeByToken(String tokenValue) {
|
||||
// 1、如果 token 为 null,直接提前返回
|
||||
if(SaFoxUtil.isEmpty(tokenValue)) {
|
||||
return null;
|
||||
}
|
||||
SaTerminalInfo terminalInfo = getTerminalInfoByToken(tokenValue);
|
||||
return terminalInfo == null ? null : terminalInfo.getDeviceType();
|
||||
}
|
||||
|
||||
// 2、获取此 token 对应的 loginId,如果为null,或者此token已被冻结,直接返回null
|
||||
Object loginId = getLoginIdNotHandle(tokenValue);
|
||||
if( ! isValidLoginId(loginId)) {
|
||||
return null;
|
||||
}
|
||||
if(getTokenActiveTimeoutByToken(tokenValue) == SaTokenDao.NOT_VALUE_EXPIRE ) {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 返回当前会话的登录设备 ID
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public String getLoginDeviceId() {
|
||||
return getLoginDeviceIdByToken(getTokenValue());
|
||||
}
|
||||
|
||||
// 3、获取这个账号的 Account-Session
|
||||
SaSession session = getSessionByLoginId(loginId, false);
|
||||
|
||||
// 4、为 null 说明尚未登录,当然也就不存在什么设备类型,直接返回 null
|
||||
if(session == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 5、遍历 Account-Session 上的客户端 token 列表,寻找当前 token 对应的设备类型
|
||||
List<SaTerminalInfo> terminalList = session.terminalListCopy();
|
||||
for (SaTerminalInfo terminal : terminalList) {
|
||||
if(terminal.getTokenValue().equals(tokenValue)) {
|
||||
return terminal.getDeviceType();
|
||||
}
|
||||
}
|
||||
|
||||
// 6、没有找到,还是返回 null
|
||||
return null;
|
||||
/**
|
||||
* 返回指定 token 会话的登录设备 ID
|
||||
*
|
||||
* @param tokenValue 指定token
|
||||
* @return /
|
||||
*/
|
||||
public String getLoginDeviceIdByToken(String tokenValue) {
|
||||
SaTerminalInfo terminalInfo = getTerminalInfoByToken(tokenValue);
|
||||
return terminalInfo == null ? null : terminalInfo.getDeviceId();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -678,6 +678,15 @@ public class StpUtil {
|
||||
stpLogic.checkActiveTimeout();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前 token 的最后活跃时间(13位时间戳),如果不存在则返回 -2
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public static long getTokenLastActiveTime() {
|
||||
return stpLogic.getTokenLastActiveTime();
|
||||
}
|
||||
|
||||
|
||||
// ------------------- 过期时间相关 -------------------
|
||||
|
||||
@ -1010,6 +1019,25 @@ public class StpUtil {
|
||||
stpLogic.forEachTerminalList(loginId, function);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前 token 指向的 SaTerminalInfo 设备信息,如果 token 无效则返回 null
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public static SaTerminalInfo getTerminalInfo() {
|
||||
return stpLogic.getTerminalInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回指定 token 指向的 SaTerminalInfo 设备信息,如果 Token 无效则返回 null
|
||||
*
|
||||
* @param tokenValue 指定 token
|
||||
* @return /
|
||||
*/
|
||||
public static SaTerminalInfo getTerminalInfoByToken(String tokenValue) {
|
||||
return stpLogic.getTerminalInfoByToken(tokenValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前会话的登录设备类型
|
||||
*
|
||||
@ -1030,12 +1058,22 @@ public class StpUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前 token 的最后活跃时间(13位时间戳),如果不存在则返回 -2
|
||||
* 返回当前会话的登录设备 ID
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public static long getTokenLastActiveTime() {
|
||||
return stpLogic.getTokenLastActiveTime();
|
||||
public static String getLoginDeviceId() {
|
||||
return stpLogic.getLoginDeviceId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回指定 token 会话的登录设备 ID
|
||||
*
|
||||
* @param tokenValue 指定token
|
||||
* @return /
|
||||
*/
|
||||
public static String getLoginDeviceIdByToken(String tokenValue) {
|
||||
return stpLogic.getLoginDeviceIdByToken(tokenValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,10 +36,17 @@ public class SaLogoutParameter {
|
||||
// --------- 单独参数
|
||||
|
||||
/**
|
||||
* 需要注销的设备类型 (如果不指定,则默认注销所有客户端)
|
||||
* 需要注销的设备类型 (为 null 代表不限制,为具体值代表只注销此设备类型的会话)
|
||||
* <br/> (此参数只在调用 StpUtil.logout(id, parame) 时有效)
|
||||
*/
|
||||
private String deviceType;
|
||||
|
||||
/**
|
||||
* 需要注销的设备ID (为 null 代表不限制,为具体值代表只注销此设备ID的会话)
|
||||
* <br/> (此参数只在调用 StpUtil.logout(id, param) 时有效)
|
||||
*/
|
||||
private String deviceId;
|
||||
|
||||
/**
|
||||
* 注销类型 (LOGOUT=注销下线、KICKOUT=踢人下线,REPLACED=顶人下线)
|
||||
*/
|
||||
@ -50,13 +57,13 @@ public class SaLogoutParameter {
|
||||
|
||||
/**
|
||||
* 注销范围 (TOKEN=只注销当前 token 的会话,ACCOUNT=注销当前 token 指向的 loginId 其所有客户端会话)
|
||||
* <br/> (此参数只在调用 StpUtil.logout() 时有效)
|
||||
* <br/> (此参数只在调用 StpUtil.logout(param) 时有效)
|
||||
*/
|
||||
private SaLogoutRange range;
|
||||
|
||||
/**
|
||||
* 如果 token 已被冻结,是否保留其操作权 (是否允许此 token 调用注销API)
|
||||
* <br/> (此参数只在调用 StpUtil.[logout/kickout/replaced]ByTokenValue("token") 时有效)
|
||||
* <br/> (此参数只在调用 StpUtil.[logout/kickout/replaced]ByTokenValue("token", param) 时有效)
|
||||
*/
|
||||
private Boolean isKeepFreezeOps;
|
||||
|
||||
@ -119,7 +126,7 @@ public class SaLogoutParameter {
|
||||
|
||||
/**
|
||||
* 获取 如果 token 已被冻结,是否保留其操作权 (是否允许此 token 调用注销API)
|
||||
* <br/> (此参数只在调用 StpUtil.[logout/kickout/replaced]ByTokenValue("token") 时有效)
|
||||
* <br/> (此参数只在调用 StpUtil.[logout/kickout/replaced]ByTokenValue("token", param) 时有效)
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
@ -129,7 +136,7 @@ public class SaLogoutParameter {
|
||||
|
||||
/**
|
||||
* 设置 如果 token 已被冻结,是否保留其操作权 (是否允许此 token 调用注销API)
|
||||
* <br/> (此参数只在调用 StpUtil.[logout/kickout/replaced]ByTokenValue("token") 时有效)
|
||||
* <br/> (此参数只在调用 StpUtil.[logout/kickout/replaced]ByTokenValue("token", param) 时有效)
|
||||
*
|
||||
* @param isKeepFreezeOps /
|
||||
* @return 对象自身
|
||||
@ -140,7 +147,8 @@ public class SaLogoutParameter {
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要注销的设备类型 (如果不指定,则默认注销所有客户端)
|
||||
* 需要注销的设备类型 (为 null 代表不限制,为具体值代表只注销此设备类型的会话)
|
||||
* <br/> (此参数只在调用 StpUtil.logout(id, parame) 时有效)
|
||||
*
|
||||
* @return deviceType /
|
||||
*/
|
||||
@ -149,7 +157,8 @@ public class SaLogoutParameter {
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要注销的设备类型 (如果不指定,则默认注销所有客户端)
|
||||
* 需要注销的设备类型 (为 null 代表不限制,为具体值代表只注销此设备类型的会话)
|
||||
* <br/> (此参数只在调用 StpUtil.logout(id, parame) 时有效)
|
||||
*
|
||||
* @param deviceType /
|
||||
* @return /
|
||||
@ -159,6 +168,28 @@ public class SaLogoutParameter {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要注销的设备ID (为 null 代表不限制,为具体值代表只注销此设备 ID 的会话)
|
||||
* <br/> (此参数只在调用 StpUtil.logout(id, parame) 时有效)
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public String getDeviceId() {
|
||||
return this.deviceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要注销的设备类型 (为 null 代表不限制,为具体值代表只注销此设备 ID 的会话)
|
||||
* <br/> (此参数只在调用 StpUtil.logout(id, parame) 时有效)
|
||||
*
|
||||
* @param deviceId /
|
||||
* @return /
|
||||
*/
|
||||
public SaLogoutParameter setDeviceId(String deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销类型 (LOGOUT=注销下线、KICKOUT=踢人下线,REPLACED=顶人下线)
|
||||
*
|
||||
@ -181,7 +212,7 @@ public class SaLogoutParameter {
|
||||
|
||||
/**
|
||||
* 注销范围 (TOKEN=只注销当前 token 的会话,ACCOUNT=注销当前 token 指向的 loginId 其所有客户端会话)
|
||||
* <br/> (此参数只在调用 StpUtil.logout() 时有效)
|
||||
* <br/> (此参数只在调用 StpUtil.logout(param) 时有效)
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
@ -191,7 +222,7 @@ public class SaLogoutParameter {
|
||||
|
||||
/**
|
||||
* 注销范围 (TOKEN=只注销当前 token 的会话,ACCOUNT=注销当前 token 指向的 loginId 其所有客户端会话)
|
||||
* <br/> (此参数只在调用 StpUtil.logout() 时有效)
|
||||
* <br/> (此参数只在调用 StpUtil.logout(param) 时有效)
|
||||
*
|
||||
* @param range /
|
||||
* @return /
|
||||
@ -208,6 +239,7 @@ public class SaLogoutParameter {
|
||||
public String toString() {
|
||||
return "SaLoginParameter ["
|
||||
+ "deviceType=" + deviceType
|
||||
+ ", deviceId=" + deviceId
|
||||
+ ", isKeepTokenSession=" + isKeepTokenSession
|
||||
+ ", isKeepFreezeOps=" + isKeepFreezeOps
|
||||
+ ", mode=" + mode
|
||||
|
@ -17,15 +17,12 @@ package cn.dev33.satoken.strategy;
|
||||
|
||||
import cn.dev33.satoken.annotation.*;
|
||||
import cn.dev33.satoken.annotation.handler.*;
|
||||
import cn.dev33.satoken.fun.strategy.SaCheckELRootMapExtendFunction;
|
||||
import cn.dev33.satoken.fun.strategy.SaCheckMethodAnnotationFunction;
|
||||
import cn.dev33.satoken.fun.strategy.SaGetAnnotationFunction;
|
||||
import cn.dev33.satoken.fun.strategy.SaIsAnnotationPresentFunction;
|
||||
import cn.dev33.satoken.fun.strategy.*;
|
||||
import cn.dev33.satoken.listener.SaTokenEventCenter;
|
||||
import cn.dev33.satoken.router.SaRouter;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Sa-Token 注解鉴权相关策略
|
||||
@ -56,7 +53,6 @@ public final class SaAnnotationStrategy {
|
||||
* 注册所有默认的注解处理器
|
||||
*/
|
||||
public void registerDefaultAnnotationHandler() {
|
||||
annotationHandlerMap.put(SaIgnore.class, new SaIgnoreHandler());
|
||||
annotationHandlerMap.put(SaCheckLogin.class, new SaCheckLoginHandler());
|
||||
annotationHandlerMap.put(SaCheckRole.class, new SaCheckRoleHandler());
|
||||
annotationHandlerMap.put(SaCheckPermission.class, new SaCheckPermissionHandler());
|
||||
@ -65,8 +61,6 @@ public final class SaAnnotationStrategy {
|
||||
annotationHandlerMap.put(SaCheckHttpBasic.class, new SaCheckHttpBasicHandler());
|
||||
annotationHandlerMap.put(SaCheckHttpDigest.class, new SaCheckHttpDigestHandler());
|
||||
annotationHandlerMap.put(SaCheckOr.class, new SaCheckOrHandler());
|
||||
annotationHandlerMap.put(SaCheckSign.class, new SaCheckSignHandler());
|
||||
annotationHandlerMap.put(SaCheckApiKey.class, new SaCheckApiKeyHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,21 +92,42 @@ public final class SaAnnotationStrategy {
|
||||
/**
|
||||
* 对一个 [Method] 对象进行注解校验 (注解鉴权内部实现)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public SaCheckMethodAnnotationFunction checkMethodAnnotation = (method) -> {
|
||||
// 遍历所有的注解处理器,检查此 method 是否具有这些指定的注解
|
||||
|
||||
// 如果 Method 或其所属 Class 上有 @SaIgnore 注解,则直接跳过整个校验过程
|
||||
if(instance.isAnnotationPresent.apply(method, SaIgnore.class)) {
|
||||
SaRouter.stop();
|
||||
}
|
||||
|
||||
// 先校验 Method 所属 Class 上的注解
|
||||
instance.checkElementAnnotation.accept(method.getDeclaringClass());
|
||||
|
||||
// 再校验 Method 上的注解
|
||||
instance.checkElementAnnotation.accept(method);
|
||||
};
|
||||
|
||||
/**
|
||||
* 对一个 [Element] 对象进行注解校验 (注解鉴权内部实现)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public SaCheckElementAnnotationFunction checkElementAnnotation = (element) -> {
|
||||
// 如果此元素上标注了 @SaCheckOr,则必须在后续判断中忽略掉其指定的 append() 类型注解判断
|
||||
List<Class<? extends Annotation>> ignoreClassList = new ArrayList<>();
|
||||
SaCheckOr checkOr = (SaCheckOr)instance.getAnnotation.apply(element, SaCheckOr.class);
|
||||
if(checkOr != null) {
|
||||
ignoreClassList = Arrays.asList(checkOr.append());
|
||||
}
|
||||
|
||||
// 遍历所有的注解处理器,检查此 element 是否具有这些指定的注解
|
||||
for (Map.Entry<Class<?>, SaAnnotationHandlerInterface<?>> entry: annotationHandlerMap.entrySet()) {
|
||||
|
||||
// 先校验 Method 所属 Class 上的注解
|
||||
Annotation classTakeAnnotation = instance.getAnnotation.apply(method.getDeclaringClass(), (Class<Annotation>)entry.getKey());
|
||||
if(classTakeAnnotation != null) {
|
||||
entry.getValue().check(classTakeAnnotation, method);
|
||||
// 忽略掉在 @SaCheckOr 中 append 字段指定的注解
|
||||
Class<Annotation> atClass = (Class<Annotation>)entry.getKey();
|
||||
if(ignoreClassList.contains(atClass)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 再校验 Method 上的注解
|
||||
Annotation methodTakeAnnotation = instance.getAnnotation.apply(method, (Class<Annotation>)entry.getKey());
|
||||
if(methodTakeAnnotation != null) {
|
||||
entry.getValue().check(methodTakeAnnotation, method);
|
||||
Annotation annotation = instance.getAnnotation.apply(element, atClass);
|
||||
if(annotation != null) {
|
||||
entry.getValue().check(annotation, element);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -121,7 +136,6 @@ public final class SaAnnotationStrategy {
|
||||
* 从元素上获取注解
|
||||
*/
|
||||
public SaGetAnnotationFunction getAnnotation = (element, annotationClass)->{
|
||||
// 默认使用jdk的注解处理器
|
||||
return element.getAnnotation(annotationClass);
|
||||
};
|
||||
|
||||
|
@ -22,6 +22,7 @@ import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.session.raw.SaRawSessionDelegator;
|
||||
import cn.dev33.satoken.strategy.SaStrategy;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
import cn.dev33.satoken.util.SaTtlMethods;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ -35,7 +36,7 @@ import java.util.*;
|
||||
* @author click33
|
||||
* @since 1.42.0
|
||||
*/
|
||||
public class SaTempTemplate {
|
||||
public class SaTempTemplate implements SaTtlMethods {
|
||||
|
||||
/**
|
||||
*默认命名空间
|
||||
@ -256,14 +257,14 @@ public class SaTempTemplate {
|
||||
if(session == null) {
|
||||
session = rawSessionDelegator.getSessionById(value, false);
|
||||
if(session == null) {
|
||||
return newTempTokenMap();
|
||||
return newTokenIndexMap();
|
||||
}
|
||||
}
|
||||
|
||||
// 重新整理索引列表
|
||||
Map<String, Long> tempTokenNewList = newTempTokenMap();
|
||||
Map<String, Long> tempTokenNewList = newTokenIndexMap();
|
||||
ArrayList<Long> tempTokenTtlList = new ArrayList<>();
|
||||
Map<String, Long> tempTokenMap = session.get(TEMP_TOKEN_MAP, this::newTempTokenMap);
|
||||
Map<String, Long> tempTokenMap = session.get(TEMP_TOKEN_MAP, this::newTokenIndexMap);
|
||||
for (Map.Entry<String, Long> entry : tempTokenMap.entrySet()) {
|
||||
long ttl = expireTimeToTtl(entry.getValue());
|
||||
if(ttl != SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||
@ -306,7 +307,7 @@ public class SaTempTemplate {
|
||||
* @param timeout /
|
||||
*/
|
||||
protected void addTempTokenIndex(SaSession session, String token, long timeout) {
|
||||
Map<String, Long> tempTokenMap = session.get(TEMP_TOKEN_MAP, this::newTempTokenMap);
|
||||
Map<String, Long> tempTokenMap = session.get(TEMP_TOKEN_MAP, this::newTokenIndexMap);
|
||||
if(! tempTokenMap.containsKey(token)) {
|
||||
tempTokenMap.put(token, ttlToExpireTime(timeout));
|
||||
session.set(TEMP_TOKEN_MAP, tempTokenMap);
|
||||
@ -319,21 +320,13 @@ public class SaTempTemplate {
|
||||
* @param token /
|
||||
*/
|
||||
protected void deleteTempTokenIndex(SaSession session, String token) {
|
||||
Map<String, Long> tempTokenMap = session.get(TEMP_TOKEN_MAP, this::newTempTokenMap);
|
||||
Map<String, Long> tempTokenMap = session.get(TEMP_TOKEN_MAP, this::newTokenIndexMap);
|
||||
if(tempTokenMap.containsKey(token)) {
|
||||
tempTokenMap.remove(token);
|
||||
session.set(TEMP_TOKEN_MAP, tempTokenMap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个新的 TempTokenMap 集合
|
||||
* @return /
|
||||
*/
|
||||
protected Map<String, Long> newTempTokenMap() {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
|
||||
// -------- 元操作
|
||||
|
||||
@ -364,55 +357,6 @@ public class SaTempTemplate {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 过期时间转 ttl (秒) 获取最大 ttl 值
|
||||
* @param tempTokenTtlList /
|
||||
* @return /
|
||||
*/
|
||||
protected long getMaxTtl(ArrayList<Long> tempTokenTtlList) {
|
||||
long maxTtl = 0;
|
||||
for (long ttl : tempTokenTtlList) {
|
||||
if(ttl == SaTokenDao.NEVER_EXPIRE) {
|
||||
maxTtl = SaTokenDao.NEVER_EXPIRE;
|
||||
break;
|
||||
}
|
||||
if(ttl > maxTtl) {
|
||||
maxTtl = ttl;
|
||||
}
|
||||
}
|
||||
return maxTtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过期时间转 ttl (秒)
|
||||
* @param expireTime /
|
||||
* @return /
|
||||
*/
|
||||
protected long expireTimeToTtl(long expireTime) {
|
||||
if(expireTime == SaTokenDao.NEVER_EXPIRE) {
|
||||
return SaTokenDao.NEVER_EXPIRE;
|
||||
}
|
||||
if(expireTime == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
}
|
||||
return (expireTime - System.currentTimeMillis()) / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* ttl (秒) 转 过期时间
|
||||
* @param ttl /
|
||||
* @return /
|
||||
*/
|
||||
protected long ttlToExpireTime(long ttl) {
|
||||
if(ttl == SaTokenDao.NEVER_EXPIRE) {
|
||||
return SaTokenDao.NEVER_EXPIRE;
|
||||
}
|
||||
if(ttl == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
}
|
||||
return ttl * 1000 + System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取:在存储临时 token 数据时,应该使用的 key
|
||||
* @param token token值
|
||||
|
@ -41,7 +41,9 @@ public class SaResult extends LinkedHashMap<String, Object> implements Serializa
|
||||
|
||||
// 预定的状态码
|
||||
public static final int CODE_SUCCESS = 200;
|
||||
public static final int CODE_ERROR = 500;
|
||||
public static final int CODE_ERROR = 500;
|
||||
public static final int CODE_NOT_PERMISSION = 403;
|
||||
public static final int CODE_NOT_LOGIN = 401;
|
||||
|
||||
/**
|
||||
* 构建
|
||||
@ -147,8 +149,10 @@ public class SaResult extends LinkedHashMap<String, Object> implements Serializa
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaResult setMap(Map<String, ?> map) {
|
||||
for (String key : map.keySet()) {
|
||||
this.put(key, map.get(key));
|
||||
if(map != null) {
|
||||
for (String key : map.keySet()) {
|
||||
this.put(key, map.get(key));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -213,6 +217,18 @@ public class SaResult extends LinkedHashMap<String, Object> implements Serializa
|
||||
return new SaResult(CODE_ERROR, msg, null);
|
||||
}
|
||||
|
||||
// 构建未登录
|
||||
public static SaResult notLogin() {
|
||||
return new SaResult(CODE_NOT_LOGIN, "not login", null);
|
||||
}
|
||||
|
||||
// 构建无权限
|
||||
public static SaResult notPermission() {
|
||||
return new SaResult(CODE_NOT_PERMISSION, "not permission", null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 构建指定状态码
|
||||
public static SaResult get(int code, String msg, Object data) {
|
||||
return new SaResult(code, msg, data);
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.util;
|
||||
|
||||
import cn.dev33.satoken.fun.SaFunction;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 代码语法糖封装
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.43.0
|
||||
*/
|
||||
public class SaSugar {
|
||||
|
||||
/**
|
||||
* 执行一个 Lambda 表达式,返回这个 Lambda 表达式的结果值,
|
||||
* <br> 方便组织代码,例如:
|
||||
* <pre>
|
||||
int value = Sugar.get(() -> {
|
||||
int a = 1;
|
||||
int b = 2;
|
||||
return a + b;
|
||||
});
|
||||
</pre>
|
||||
* @param <R> 返回值类型
|
||||
* @param lambda lambda 表达式
|
||||
* @return lambda 的执行结果
|
||||
*/
|
||||
public static <R> R get(Supplier<R> lambda) {
|
||||
return lambda.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行一个 Lambda 表达式
|
||||
* <br> 方便组织代码,例如:
|
||||
* <pre>
|
||||
Sugar.exe(() -> {
|
||||
int a = 1;
|
||||
int b = 2;
|
||||
return a + b;
|
||||
});
|
||||
</pre>
|
||||
* @param lambda lambda 表达式
|
||||
*/
|
||||
public static void exe(SaFunction lambda) {
|
||||
lambda.run();
|
||||
}
|
||||
|
||||
}
|
@ -36,7 +36,7 @@ public class SaTokenConsts {
|
||||
/**
|
||||
* Sa-Token 当前版本号
|
||||
*/
|
||||
public static final String VERSION_NO = "v1.42.0";
|
||||
public static final String VERSION_NO = "v1.44.0";
|
||||
|
||||
/**
|
||||
* Sa-Token 开源地址 Gitee
|
||||
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.util;
|
||||
|
||||
import cn.dev33.satoken.dao.SaTokenDao;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* TTL 操作工具方法
|
||||
*
|
||||
* @author click33
|
||||
* @since 1.43.0
|
||||
*/
|
||||
public interface SaTtlMethods {
|
||||
|
||||
/**
|
||||
* 获取一个新的 Token 集合
|
||||
* @return /
|
||||
*/
|
||||
default List<String> newTokenValueList() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个新的 TokenIndexMap 集合
|
||||
* @return /
|
||||
*/
|
||||
default Map<String, Long> newTokenIndexMap() {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最大 ttl 值
|
||||
* @param ttlList /
|
||||
* @return /
|
||||
*/
|
||||
default long getMaxTtl(ArrayList<Long> ttlList) {
|
||||
long maxTtl = 0;
|
||||
for (long ttl : ttlList) {
|
||||
if(ttl == SaTokenDao.NEVER_EXPIRE) {
|
||||
maxTtl = SaTokenDao.NEVER_EXPIRE;
|
||||
break;
|
||||
}
|
||||
if(ttl > maxTtl) {
|
||||
maxTtl = ttl;
|
||||
}
|
||||
}
|
||||
return maxTtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最大 ttl 值:过期时间 (13位时间戳) 转 ttl (秒)
|
||||
* @param expireTimeList /
|
||||
* @return /
|
||||
*/
|
||||
default long getMaxTtlByExpireTime(Collection<Long> expireTimeList) {
|
||||
long maxTtl = 0;
|
||||
for (long expireTime : expireTimeList) {
|
||||
long ttl = expireTimeToTtl(expireTime);
|
||||
if(ttl == SaTokenDao.NEVER_EXPIRE) {
|
||||
maxTtl = SaTokenDao.NEVER_EXPIRE;
|
||||
break;
|
||||
}
|
||||
if(ttl > maxTtl) {
|
||||
maxTtl = ttl;
|
||||
}
|
||||
}
|
||||
return maxTtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 过期时间 (13位时间戳) 转 (13位时间戳) ttl (秒)
|
||||
* @param expireTime /
|
||||
* @return /
|
||||
*/
|
||||
default long expireTimeToTtl(long expireTime) {
|
||||
if(expireTime == SaTokenDao.NEVER_EXPIRE) {
|
||||
return SaTokenDao.NEVER_EXPIRE;
|
||||
}
|
||||
if(expireTime == SaTokenDao.NOT_VALUE_EXPIRE) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
}
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if(expireTime < currentTime) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
}
|
||||
return (expireTime - currentTime) / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* ttl (秒) 转 过期时间 (13位时间戳)
|
||||
* @param ttl /
|
||||
* @return /
|
||||
*/
|
||||
default long ttlToExpireTime(long ttl) {
|
||||
if(ttl == SaTokenDao.NEVER_EXPIRE) {
|
||||
return SaTokenDao.NEVER_EXPIRE;
|
||||
}
|
||||
if(ttl < 0) {
|
||||
return SaTokenDao.NOT_VALUE_EXPIRE;
|
||||
}
|
||||
return ttl * 1000 + System.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
@ -38,13 +38,15 @@
|
||||
<module>sa-token-demo-springboot-low-version</module>
|
||||
<module>sa-token-demo-springboot-redis</module>
|
||||
<module>sa-token-demo-springboot-redisson</module>
|
||||
<module>sa-token-demo-sse</module>
|
||||
<module>sa-token-demo-ssm</module>
|
||||
<module>sa-token-demo-sso/sa-token-demo-sso-server</module>
|
||||
<module>sa-token-demo-sso/sa-token-demo-sso1-client</module>
|
||||
<module>sa-token-demo-sso/sa-token-demo-sso2-client</module>
|
||||
<module>sa-token-demo-sso/sa-token-demo-sso3-client</module>
|
||||
<module>sa-token-demo-sso/sa-token-demo-sso3-client-test2</module>
|
||||
<module>sa-token-demo-sso/sa-token-demo-sso3-client-nosdk</module>
|
||||
<module>sa-token-demo-sso/sa-token-demo-sso3-client-resdk</module>
|
||||
<module>sa-token-demo-sso/sa-token-demo-sso3-client-anon</module>
|
||||
<module>sa-token-demo-sso-for-solon/sa-token-demo-sso-server-solon</module>
|
||||
<module>sa-token-demo-sso-for-solon/sa-token-demo-sso1-client-solon</module>
|
||||
<module>sa-token-demo-sso-for-solon/sa-token-demo-sso2-client-solon</module>
|
||||
@ -55,8 +57,9 @@
|
||||
<module>sa-token-demo-webflux-springboot3</module>
|
||||
<module>sa-token-demo-websocket</module>
|
||||
<module>sa-token-demo-websocket-spring</module>
|
||||
<module>sa-token-demo-loveqq-boot</module>
|
||||
|
||||
</modules>
|
||||
</modules>
|
||||
|
||||
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@ -47,6 +47,13 @@
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Sa-Token 整合 API Key -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-apikey</artifactId>
|
||||
<version>${sa-token.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 热刷新 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.pj;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.apikey.SaApiKeyManager;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@ -9,8 +10,9 @@ public class SaTokenApiKeyApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SaTokenApiKeyApplication.class, args);
|
||||
System.out.println("\n启动成功,Sa-Token 配置如下:" + SaManager.getConfig());
|
||||
System.out.println("\n测试访问:http://localhost:8081/index.html");
|
||||
System.out.println("启动成功:Sa-Token 配置如下:" + SaManager.getConfig());
|
||||
System.out.println("启动成功:API Key 配置如下:" + SaApiKeyManager.getConfig());
|
||||
System.out.println("测试访问:http://localhost:8081/index.html");
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package com.pj.test;
|
||||
|
||||
import cn.dev33.satoken.apikey.SaApiKeyUtil;
|
||||
import cn.dev33.satoken.apikey.model.ApiKeyModel;
|
||||
import cn.dev33.satoken.apikey.template.SaApiKeyUtil;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
@ -1,9 +1,9 @@
|
||||
package com.pj.test;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckApiKey;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import cn.dev33.satoken.apikey.SaApiKeyUtil;
|
||||
import cn.dev33.satoken.apikey.annotation.SaCheckApiKey;
|
||||
import cn.dev33.satoken.apikey.model.ApiKeyModel;
|
||||
import cn.dev33.satoken.apikey.template.SaApiKeyUtil;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
<java.run.main.class>com.pj.SaTokenAsyncApplication</java.run.main.class>
|
||||
</properties>
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@ -73,7 +73,7 @@
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-bom</artifactId>
|
||||
<version>1.42.0</version>
|
||||
<version>1.44.0</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -74,7 +74,7 @@ public class MySaTokenListener implements SaTokenListener {
|
||||
|
||||
/** 每次Token续期时触发 */
|
||||
@Override
|
||||
public void doRenewTimeout(String tokenValue, Object loginId, long timeout) {
|
||||
public void doRenewTimeout(String loginType, Object loginId, String tokenValue, long timeout) {
|
||||
System.out.println("---------- 自定义侦听器实现 doRenewTimeout");
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ import cn.dev33.satoken.exception.SaTokenException;
|
||||
import com.pj.satoken.custom_annotation.CheckAccount;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 CheckAccount 的处理器
|
||||
@ -25,7 +25,7 @@ public class CheckAccountHandler implements SaAnnotationHandlerInterface<CheckAc
|
||||
|
||||
// 每次请求校验注解时,会执行的方法
|
||||
@Override
|
||||
public void checkMethod(CheckAccount at, Method method) {
|
||||
public void checkMethod(CheckAccount at, AnnotatedElement element) {
|
||||
// 获取前端请求提交的参数
|
||||
String name = SaHolder.getRequest().getParamNotNull("name");
|
||||
String pwd = SaHolder.getRequest().getParamNotNull("pwd");
|
||||
|
@ -6,7 +6,7 @@ import com.pj.satoken.StpUserUtil;
|
||||
import com.pj.satoken.custom_annotation.SaUserCheckLogin;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaUserCheckLogin 的处理器
|
||||
@ -22,7 +22,7 @@ public class SaUserCheckLoginHandler implements SaAnnotationHandlerInterface<SaU
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaUserCheckLogin at, Method method) {
|
||||
public void checkMethod(SaUserCheckLogin at, AnnotatedElement element) {
|
||||
SaCheckLoginHandler._checkMethod(StpUserUtil.TYPE);
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ import com.pj.satoken.StpUserUtil;
|
||||
import com.pj.satoken.custom_annotation.SaUserCheckPermission;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaUserCheckPermission 的处理器
|
||||
@ -22,7 +22,7 @@ public class SaUserCheckPermissionHandler implements SaAnnotationHandlerInterfac
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaUserCheckPermission at, Method method) {
|
||||
public void checkMethod(SaUserCheckPermission at, AnnotatedElement element) {
|
||||
SaCheckPermissionHandler._checkMethod(StpUserUtil.TYPE, at.value(), at.mode(), at.orRole());
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ import com.pj.satoken.StpUserUtil;
|
||||
import com.pj.satoken.custom_annotation.SaUserCheckRole;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaUserCheckRole 的处理器
|
||||
@ -22,7 +22,7 @@ public class SaUserCheckRoleHandler implements SaAnnotationHandlerInterface<SaUs
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaUserCheckRole at, Method method) {
|
||||
public void checkMethod(SaUserCheckRole at, AnnotatedElement element) {
|
||||
SaCheckRoleHandler._checkMethod(StpUserUtil.TYPE, at.value(), at.mode());
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ import com.pj.satoken.StpUserUtil;
|
||||
import com.pj.satoken.custom_annotation.SaUserCheckSafe;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
|
||||
/**
|
||||
* 注解 SaUserCheckPermission 的处理器
|
||||
@ -22,7 +22,7 @@ public class SaUserCheckSafeHandler implements SaAnnotationHandlerInterface<SaUs
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkMethod(SaUserCheckSafe at, Method method) {
|
||||
public void checkMethod(SaUserCheckSafe at, AnnotatedElement element) {
|
||||
SaCheckSafeHandler._checkMethod(StpUserUtil.TYPE, at.value());
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
<java.run.main.class>com.pj.SaTokenDeviceLockApplication</java.run.main.class>
|
||||
</properties>
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
<dubbo.version>2.7.21</dubbo.version>
|
||||
<nacos.version>1.4.2</nacos.version>
|
||||
</properties>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
<dubbo.version>2.7.21</dubbo.version>
|
||||
<nacos.version>1.4.2</nacos.version>
|
||||
</properties>
|
||||
|
@ -10,14 +10,15 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<!--<version>2.3.1.RELEASE</version>-->
|
||||
<version>2.5.15</version>
|
||||
<!-- <version>2.5.15</version>-->
|
||||
<version>3.4.3</version>
|
||||
</parent>
|
||||
|
||||
<!-- 指定一些属性 -->
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<java.version>17</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
<dubbo.version>3.2.2</dubbo.version>
|
||||
<nacos.version>2.2.2</nacos.version>
|
||||
</properties>
|
||||
@ -33,7 +34,7 @@
|
||||
<!-- Sa-Token -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot-starter</artifactId>
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
<version>${sa-token.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
@ -2,18 +2,19 @@ server:
|
||||
# 端口号
|
||||
port: 8081
|
||||
|
||||
spring:
|
||||
# redis配置
|
||||
redis:
|
||||
# Redis数据库索引(默认为0)
|
||||
database: 0
|
||||
# Redis服务器地址
|
||||
host: 127.0.0.1
|
||||
# Redis服务器连接端口
|
||||
port: 6379
|
||||
# Redis服务器连接密码(默认为空)
|
||||
password:
|
||||
# 连接超时时间
|
||||
spring:
|
||||
data:
|
||||
# redis配置
|
||||
redis:
|
||||
# Redis数据库索引(默认为0)
|
||||
database: 0
|
||||
# Redis服务器地址
|
||||
host: 127.0.0.1
|
||||
# Redis服务器连接端口
|
||||
port: 6379
|
||||
# Redis服务器连接密码(默认为空)
|
||||
password:
|
||||
# 连接超时时间
|
||||
|
||||
dubbo:
|
||||
application:
|
||||
|
@ -10,14 +10,15 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<!--<version>2.3.1.RELEASE</version>-->
|
||||
<version>2.5.15</version>
|
||||
<!-- <version>2.5.15</version>-->
|
||||
<version>3.4.3</version>
|
||||
</parent>
|
||||
|
||||
<!-- 指定一些属性 -->
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<java.version>17</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
<dubbo.version>3.2.2</dubbo.version>
|
||||
<nacos.version>2.2.2</nacos.version>
|
||||
</properties>
|
||||
@ -33,7 +34,7 @@
|
||||
<!-- Sa-Token -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot-starter</artifactId>
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
<version>${sa-token.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
@ -14,9 +14,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@SpringBootApplication
|
||||
public class Dubbo3ProviderApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
public static void main(String[] args) throws Exception {
|
||||
SpringApplication.run(Dubbo3ProviderApplication.class, args);
|
||||
System.out.println("Dubbo3ProviderApplication 启动成功");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -9,9 +9,18 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class TestController {
|
||||
|
||||
@Autowired
|
||||
private DemoService demoService;
|
||||
|
||||
|
||||
// 如果把 @Autowired 改为 @DubboReference
|
||||
// 则可能在首次调用 dubbo 服务时控制台出现以下异常(只打印异常信息,不影响调用):
|
||||
// java.lang.reflect.InaccessibleObjectException: Unable to make field private byte java.lang.StackTraceElement.format accessible:
|
||||
// module java.base does not "opens java.lang" to unnamed module @3a52dba3
|
||||
//
|
||||
// 在启动参数上加上如下即可解决:
|
||||
// --add-opens java.base/java.math=ALL-UNNAMED
|
||||
|
||||
@Autowired
|
||||
public DemoService demoService;
|
||||
|
||||
// test
|
||||
@RequestMapping("test")
|
||||
|
@ -2,19 +2,20 @@ server:
|
||||
# 端口号
|
||||
port: 8080
|
||||
|
||||
spring:
|
||||
# redis配置
|
||||
redis:
|
||||
# Redis数据库索引(默认为0)
|
||||
database: 0
|
||||
# Redis服务器地址
|
||||
host: 127.0.0.1
|
||||
# Redis服务器连接端口
|
||||
port: 6379
|
||||
# Redis服务器连接密码(默认为空)
|
||||
password:
|
||||
# 连接超时时间
|
||||
timeout: 10s
|
||||
spring:
|
||||
data:
|
||||
# redis配置
|
||||
redis:
|
||||
# Redis数据库索引(默认为0)
|
||||
database: 0
|
||||
# Redis服务器地址
|
||||
host: 127.0.0.1
|
||||
# Redis服务器连接端口
|
||||
port: 6379
|
||||
# Redis服务器连接密码(默认为空)
|
||||
password:
|
||||
# 连接超时时间
|
||||
timeout: 10s
|
||||
|
||||
# Dubbo
|
||||
dubbo:
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -27,7 +27,7 @@
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<lombok.version>1.18.10</lombok.version>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
74
sa-token-demo/sa-token-demo-loveqq-boot/pom.xml
Normal file
74
sa-token-demo/sa-token-demo-loveqq-boot/pom.xml
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.kfyty</groupId>
|
||||
<artifactId>loveqq-framework</artifactId>
|
||||
<version>1.1.2</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<artifactId>sa-token-demo-loveqq-boot</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<jdk.version>17</jdk.version>
|
||||
<java.version>17</java.version>
|
||||
<maven.source.version>17</maven.source.version>
|
||||
<maven.compile.version>17</maven.compile.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- 引导启动模块 -->
|
||||
<dependency>
|
||||
<groupId>com.kfyty</groupId>
|
||||
<artifactId>loveqq-boot</artifactId>
|
||||
<version>${loveqq.framework.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- reactor-netty 服务器,同时支持命令式/响应式编程范式 -->
|
||||
<dependency>
|
||||
<groupId>com.kfyty</groupId>
|
||||
<artifactId>loveqq-boot-starter-netty</artifactId>
|
||||
<version>${loveqq.framework.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token 集成 -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-loveqq-boot-starter</artifactId>
|
||||
<version>${sa-token.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- logback 启动器 -->
|
||||
<dependency>
|
||||
<groupId>com.kfyty</groupId>
|
||||
<artifactId>loveqq-boot-starter-logback</artifactId>
|
||||
<version>${loveqq.framework.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- yaml 支持,默认使用 properties 文件,如果使用 yaml 需自行引入依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,21 @@
|
||||
package com.pj;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import com.kfyty.loveqq.framework.boot.K;
|
||||
import com.kfyty.loveqq.framework.core.autoconfig.annotation.BootApplication;
|
||||
import com.kfyty.loveqq.framework.web.core.autoconfig.annotation.EnableWebMvc;
|
||||
|
||||
/**
|
||||
* Sa-Token 整合 loveqq-framework 示例
|
||||
*
|
||||
* @author kfyty725
|
||||
*/
|
||||
@EnableWebMvc
|
||||
@BootApplication
|
||||
public class SaTokenLoveqqApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
K.run(SaTokenLoveqqApplication.class, args);
|
||||
System.out.println("\n启动成功:Sa-Token配置如下:" + SaManager.getConfig());
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.pj.satoken;
|
||||
|
||||
import cn.dev33.satoken.context.model.SaTokenContextModelBox;
|
||||
import cn.dev33.satoken.loveqq.boot.utils.SaTokenContextUtil;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.kfyty.loveqq.framework.core.autoconfig.annotation.Component;
|
||||
import com.kfyty.loveqq.framework.web.core.filter.Filter;
|
||||
import com.kfyty.loveqq.framework.web.core.filter.FilterChain;
|
||||
import com.kfyty.loveqq.framework.web.core.http.ServerRequest;
|
||||
import com.kfyty.loveqq.framework.web.core.http.ServerResponse;
|
||||
|
||||
/**
|
||||
* 自定义过滤器
|
||||
*/
|
||||
@Component
|
||||
public class MyFilter implements Filter {
|
||||
/**
|
||||
* 实现该方法,可以实现 servlet/reactor 的统一
|
||||
* 但是该方法内部是同步方法,若需要异步,可以实现仅 reactor 支持的 {@link Filter#doFilter(ServerRequest, ServerResponse, FilterChain)} 方法
|
||||
*
|
||||
* @param request 请求
|
||||
* @param response 响应
|
||||
*/
|
||||
@Override
|
||||
public Continue doFilter(ServerRequest request, ServerResponse response) {
|
||||
System.out.println("进入自定义过滤器");
|
||||
|
||||
// 先 set 上下文,再调用 Sa-Token 同步 API,并在 finally 里清除上下文
|
||||
SaTokenContextModelBox prev = SaTokenContextUtil.setContext(request, response);
|
||||
try {
|
||||
System.out.println(StpUtil.isLogin());
|
||||
} finally {
|
||||
SaTokenContextUtil.clearContext(prev);
|
||||
}
|
||||
|
||||
return Continue.TRUE;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.pj.satoken;
|
||||
|
||||
import cn.dev33.satoken.loveqq.boot.filter.SaRequestFilter;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import com.kfyty.loveqq.framework.core.autoconfig.annotation.Bean;
|
||||
import com.kfyty.loveqq.framework.core.autoconfig.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* [Sa-Token 权限认证] 配置类
|
||||
* @author click33
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
public class SaTokenConfigure {
|
||||
|
||||
/**
|
||||
* 注册 [sa-token全局过滤器]
|
||||
*/
|
||||
@Bean
|
||||
public SaRequestFilter getSaReactorFilter() {
|
||||
return new SaRequestFilter()
|
||||
// 指定 [拦截路由]
|
||||
.addInclude("/**")
|
||||
// 指定 [放行路由]
|
||||
.addExclude("/favicon.ico")
|
||||
// 指定[认证函数]: 每次请求执行
|
||||
.setAuth(r -> {
|
||||
System.out.println("---------- sa全局认证");
|
||||
// SaRouter.match("/test/test", () -> StpUtil.checkLogin());
|
||||
})
|
||||
// 指定[异常处理函数]:每次[认证函数]发生异常时执行此函数
|
||||
.setError(e -> {
|
||||
System.out.println("---------- sa全局异常 ");
|
||||
e.printStackTrace();
|
||||
return SaResult.error(e.getMessage());
|
||||
})
|
||||
;
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.pj.satoken;
|
||||
|
||||
import cn.dev33.satoken.stp.StpInterface;
|
||||
import com.kfyty.loveqq.framework.core.autoconfig.annotation.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 自定义权限验证接口扩展
|
||||
*/
|
||||
@Component // 打开此注解,保证此类被springboot扫描,即可完成sa-token的自定义权限验证扩展
|
||||
public class StpInterfaceImpl implements StpInterface {
|
||||
|
||||
/**
|
||||
* 返回一个账号所拥有的权限码集合
|
||||
*/
|
||||
@Override
|
||||
public List<String> getPermissionList(Object loginId, String loginType) {
|
||||
// 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限
|
||||
List<String> list = new ArrayList<String>();
|
||||
list.add("101");
|
||||
list.add("user-add");
|
||||
list.add("user-delete");
|
||||
list.add("user-update");
|
||||
list.add("user-get");
|
||||
list.add("article-get");
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回一个账号所拥有的角色标识集合
|
||||
*/
|
||||
@Override
|
||||
public List<String> getRoleList(Object loginId, String loginType) {
|
||||
// 本list仅做模拟,实际项目中要根据具体业务逻辑来查询角色
|
||||
List<String> list = new ArrayList<String>();
|
||||
list.add("admin");
|
||||
list.add("super-admin");
|
||||
return list;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.pj.test;
|
||||
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import com.kfyty.loveqq.framework.web.core.annotation.ExceptionHandler;
|
||||
import com.kfyty.loveqq.framework.web.core.annotation.RestControllerAdvice;
|
||||
|
||||
/**
|
||||
* 全局异常处理
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
public class GlobalException {
|
||||
|
||||
@ExceptionHandler
|
||||
public SaResult handlerException(Exception e) {
|
||||
e.printStackTrace();
|
||||
return SaResult.error(e.getMessage());
|
||||
}
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
package com.pj.test;
|
||||
|
||||
import cn.dev33.satoken.loveqq.boot.context.SaReactorHolder;
|
||||
import cn.dev33.satoken.loveqq.boot.utils.SaTokenContextUtil;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import com.kfyty.loveqq.framework.core.autoconfig.annotation.Autowired;
|
||||
import com.kfyty.loveqq.framework.web.core.annotation.GetMapping;
|
||||
import com.kfyty.loveqq.framework.web.core.annotation.RequestMapping;
|
||||
import com.kfyty.loveqq.framework.web.core.annotation.RestController;
|
||||
import com.kfyty.loveqq.framework.web.core.annotation.bind.CookieValue;
|
||||
import com.kfyty.loveqq.framework.web.core.annotation.bind.RequestParam;
|
||||
import com.kfyty.loveqq.framework.web.core.http.ServerRequest;
|
||||
import com.kfyty.loveqq.framework.web.core.http.ServerResponse;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* 测试专用 Controller
|
||||
* 本示例是基于 reactor 编写,如果是 servlet,去除 SaReactorHolder/SaTokenContextUtil 包装,直接调用 sa-token api 即可
|
||||
*
|
||||
* @author click33
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/test/")
|
||||
public class TestController {
|
||||
|
||||
@Autowired
|
||||
UserService userService;
|
||||
|
||||
// 登录测试:Controller 里调用 Sa-Token API --- http://localhost:8081/test/login
|
||||
@GetMapping("login")
|
||||
public Mono<SaResult> login(@RequestParam(defaultValue = "10001") String id) {
|
||||
return SaReactorHolder.sync(() -> {
|
||||
StpUtil.login(id);
|
||||
return SaResult.ok("登录成功");
|
||||
});
|
||||
}
|
||||
|
||||
// API测试:手动设置上下文、try-finally 形式 --- http://localhost:8081/test/isLogin
|
||||
@GetMapping("isLogin")
|
||||
public SaResult isLogin(ServerRequest request, ServerResponse response) {
|
||||
try {
|
||||
SaTokenContextUtil.setContext(request, response);
|
||||
System.out.println("是否登录:" + StpUtil.isLogin());
|
||||
return SaResult.data(StpUtil.getTokenInfo());
|
||||
} finally {
|
||||
SaTokenContextUtil.clearContext(null);
|
||||
}
|
||||
}
|
||||
|
||||
// API测试:手动设置上下文、lambda 表达式形式 --- http://localhost:8081/test/isLogin2
|
||||
@GetMapping("isLogin2")
|
||||
public SaResult isLogin2(ServerRequest request, ServerResponse response) {
|
||||
SaResult res = SaTokenContextUtil.setContext(request, response, () -> {
|
||||
System.out.println("是否登录:" + StpUtil.isLogin());
|
||||
return SaResult.data(StpUtil.getTokenInfo());
|
||||
});
|
||||
return SaResult.data(res);
|
||||
}
|
||||
|
||||
// API测试:自动设置上下文、lambda 表达式形式 --- http://localhost:8081/test/isLogin3
|
||||
@GetMapping("isLogin3")
|
||||
public Mono<SaResult> isLogin3() {
|
||||
return SaReactorHolder.sync(() -> {
|
||||
System.out.println("是否登录:" + StpUtil.isLogin());
|
||||
userService.isLogin();
|
||||
return SaResult.data(StpUtil.getTokenInfo());
|
||||
});
|
||||
}
|
||||
|
||||
// API测试:自动设置上下文、调用 userService Mono 方法 --- http://localhost:8081/test/isLogin4
|
||||
@GetMapping("isLogin4")
|
||||
public Mono<SaResult> isLogin4() {
|
||||
return userService.findUserIdByNamePwd("ZhangSan", "123456")
|
||||
.flatMap(userId -> SaReactorHolder.sync(() -> {
|
||||
StpUtil.login(userId);
|
||||
return SaResult.data(StpUtil.getTokenInfo());
|
||||
}));
|
||||
}
|
||||
|
||||
// API测试:切换线程、复杂嵌套调用 --- http://localhost:8081/test/isLogin5
|
||||
@GetMapping("isLogin5")
|
||||
public Mono<SaResult> isLogin5() {
|
||||
System.out.println("线程id-----" + Thread.currentThread().getId());
|
||||
// 要点:在流里调用 Sa-Token API 之前,必须用 SaReactorHolder.sync( () -> {} ) 进行包裹
|
||||
return Mono.delay(Duration.ofSeconds(1))
|
||||
.doOnNext(r -> System.out.println("线程id-----" + Thread.currentThread().getId()))
|
||||
.map(r -> SaReactorHolder.sync(() -> userService.isLogin()))
|
||||
.map(r -> userService.findUserIdByNamePwd("ZhangSan", "123456"))
|
||||
.map(r -> SaReactorHolder.sync(() -> userService.isLogin()))
|
||||
.flatMap(isLogin -> {
|
||||
System.out.println("是否登录 " + isLogin);
|
||||
return SaReactorHolder.sync(() -> {
|
||||
System.out.println("是否登录 " + StpUtil.isLogin());
|
||||
return SaResult.data(StpUtil.getTokenInfo());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// API测试:使用上下文无关的API --- http://localhost:8081/test/isLogin6
|
||||
@GetMapping("isLogin6")
|
||||
public SaResult isLogin6(@CookieValue("satoken") String satoken) {
|
||||
System.out.println("token 为:" + satoken);
|
||||
System.out.println("登录人:" + StpUtil.getLoginIdByToken(satoken));
|
||||
return SaResult.ok("登录人:" + StpUtil.getLoginIdByToken(satoken));
|
||||
}
|
||||
|
||||
// 测试 浏览器访问: http://localhost:8081/test/test
|
||||
@GetMapping("test")
|
||||
public SaResult test() {
|
||||
System.out.println("线程id------- " + Thread.currentThread().getId());
|
||||
return SaResult.ok();
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.pj.test;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.kfyty.loveqq.framework.core.autoconfig.annotation.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* 模拟 Service 方法
|
||||
* @author click33
|
||||
* @since 2025/4/6
|
||||
*/
|
||||
@Service
|
||||
public class UserService {
|
||||
|
||||
public boolean isLogin() {
|
||||
System.out.println("UserService 里调用 API 测试,是否登录:" + StpUtil.isLogin());
|
||||
return StpUtil.isLogin();
|
||||
}
|
||||
|
||||
public Mono<Long> findUserIdByNamePwd(String name, String pwd) {
|
||||
// ...
|
||||
return Mono.just(10001L);
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
# 端口
|
||||
k:
|
||||
server:
|
||||
port: 8081
|
@ -17,7 +17,7 @@
|
||||
<java.version>1.8</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<java.version>1.8</java.version>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -16,12 +16,14 @@ import java.util.List;
|
||||
@Component
|
||||
public class SaClientMockDao {
|
||||
|
||||
public List<SaClientModel> list = new ArrayList<>();
|
||||
public List<SaClientModel> list;
|
||||
|
||||
/**
|
||||
* 构造方法,添加三个模拟应用
|
||||
*/
|
||||
public SaClientMockDao(){
|
||||
public void init(){
|
||||
list = new ArrayList<>();
|
||||
|
||||
// 模拟应用1
|
||||
SaClientModel client1 = new SaClientModel()
|
||||
.setClientId("1001") // client id
|
||||
@ -77,6 +79,9 @@ public class SaClientMockDao {
|
||||
* @return 应用对象
|
||||
*/
|
||||
public SaClientModel getClientModel(String clientId) {
|
||||
if(list == null) {
|
||||
init();
|
||||
}
|
||||
return list.stream()
|
||||
.filter(e -> e.getClientId().equals(clientId))
|
||||
.findFirst()
|
||||
|
@ -3,6 +3,7 @@ package com.pj.oauth2;
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.oauth2.config.SaOAuth2ServerConfig;
|
||||
import cn.dev33.satoken.oauth2.processor.SaOAuth2ServerProcessor;
|
||||
import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -32,12 +33,12 @@ public class SaOAuth2ServerController {
|
||||
@Autowired
|
||||
public void configOAuth2Server(SaOAuth2ServerConfig oauth2Server) {
|
||||
// 未登录的视图
|
||||
oauth2Server.notLoginView = ()->{
|
||||
SaOAuth2Strategy.instance.notLoginView = ()->{
|
||||
return new ModelAndView("login.html");
|
||||
};
|
||||
|
||||
// 登录处理函数
|
||||
oauth2Server.doLoginHandle = (name, pwd) -> {
|
||||
SaOAuth2Strategy.instance.doLoginHandle = (name, pwd) -> {
|
||||
if("sa".equals(name) && "123456".equals(pwd)) {
|
||||
StpUtil.login(10001);
|
||||
return SaResult.ok().set("satoken", StpUtil.getTokenValue());
|
||||
@ -46,7 +47,7 @@ public class SaOAuth2ServerController {
|
||||
};
|
||||
|
||||
// 授权确认视图
|
||||
oauth2Server.confirmView = (clientId, scopes)->{
|
||||
SaOAuth2Strategy.instance.confirmView = (clientId, scopes)->{
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("clientId", clientId);
|
||||
map.put("scope", scopes);
|
||||
|
@ -0,0 +1,27 @@
|
||||
//package com.pj.oauth2.custom_grant_type;
|
||||
//
|
||||
//import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
|
||||
//import cn.dev33.satoken.oauth2.granttype.handler.PasswordGrantTypeHandler;
|
||||
//import cn.dev33.satoken.oauth2.granttype.handler.model.PasswordAuthResult;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//
|
||||
///**
|
||||
// * 自定义 Password Grant_Type 授权模式处理器认证过程
|
||||
// *
|
||||
// * @author click33
|
||||
// * @since 2025/5/11
|
||||
// */
|
||||
//@Component
|
||||
//public class CustomPasswordGrantTypeHandler extends PasswordGrantTypeHandler {
|
||||
//
|
||||
// @Override
|
||||
// public PasswordAuthResult loginByUsernamePassword(String username, String password) {
|
||||
// if("sa".equals(username) && "123456".equals(password)) {
|
||||
// long userId = 10001;
|
||||
// return new PasswordAuthResult(userId);
|
||||
// } else {
|
||||
// throw new SaOAuth2Exception("无效账号密码");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
@ -1,4 +1,4 @@
|
||||
//package com.pj.oauth2.custom;
|
||||
//package com.pj.oauth2.custom_grant_type;
|
||||
//
|
||||
//import cn.dev33.satoken.SaManager;
|
||||
//import cn.dev33.satoken.context.model.SaRequest;
|
@ -1,4 +1,4 @@
|
||||
//package com.pj.oauth2.custom;
|
||||
//package com.pj.oauth2.custom_grant_type;
|
||||
//
|
||||
//import cn.dev33.satoken.SaManager;
|
||||
//import cn.dev33.satoken.util.SaFoxUtil;
|
@ -1,4 +1,4 @@
|
||||
//package com.pj.oauth2.custom;
|
||||
//package com.pj.oauth2.custom_scope;
|
||||
//
|
||||
//import cn.dev33.satoken.oauth2.data.model.oidc.IdTokenModel;
|
||||
//import cn.dev33.satoken.oauth2.scope.handler.OidcScopeHandler;
|
||||
@ -19,10 +19,11 @@
|
||||
// System.out.println("----- 为 idToken 追加扩展字段 ----- ");
|
||||
//
|
||||
// idToken.extraData.put("uid", userId); // 用户id
|
||||
// idToken.extraData.put("nickname", "lin_xiao_lin"); // 昵称
|
||||
// idToken.extraData.put("nickname", "linXiaoLin"); // 昵称
|
||||
// idToken.extraData.put("picture", "https://sa-token.cc/logo.png"); // 头像
|
||||
// idToken.extraData.put("email", "456456@xx.com"); // 邮箱
|
||||
// idToken.extraData.put("phone_number", "13144556677"); // 手机号
|
||||
//
|
||||
// // 更多字段 ...
|
||||
// // 可参考:https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
|
||||
//
|
@ -1,4 +1,4 @@
|
||||
//package com.pj.oauth2.custom;
|
||||
//package com.pj.oauth2.custom_scope;
|
||||
//
|
||||
//import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
|
||||
//import cn.dev33.satoken.oauth2.data.model.ClientTokenModel;
|
||||
@ -9,17 +9,20 @@
|
||||
//import java.util.Map;
|
||||
//
|
||||
///**
|
||||
// * 自定义 userinfo scope 处理器
|
||||
// * @author click33
|
||||
// * @since 2024/8/20
|
||||
// */
|
||||
//@Component
|
||||
//public class UserinfoScopeHandler implements SaOAuth2ScopeHandlerInterface {
|
||||
//
|
||||
// // 指示当前处理器所要处理的 scope
|
||||
// @Override
|
||||
// public String getHandlerScope() {
|
||||
// return "userinfo";
|
||||
// }
|
||||
//
|
||||
// // 当构建的 AccessToken 具有此权限时,所需要执行的方法
|
||||
// @Override
|
||||
// public void workAccessToken(AccessTokenModel at) {
|
||||
// System.out.println("--------- userinfo 权限,加工 AccessTokenModel --------- ");
|
||||
@ -34,8 +37,16 @@
|
||||
// at.extraData.put("userinfo", map);
|
||||
// }
|
||||
//
|
||||
// // 当构建的 ClientToken 具有此权限时,所需要执行的方法
|
||||
// @Override
|
||||
// public void workClientToken(ClientTokenModel ct) {
|
||||
// }
|
||||
//
|
||||
// // 当使用 RefreshToken 刷新 AccessToken 时,是否重新执行 workAccessToken 构建方法
|
||||
// // 在一些实时性较高的数据中需要指定为 true
|
||||
// @Override
|
||||
// public boolean refreshAccessTokenIsWork() {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
//}
|
@ -8,10 +8,12 @@ import cn.dev33.satoken.oauth2.consts.SaOAuth2Consts;
|
||||
import cn.dev33.satoken.oauth2.data.generate.SaOAuth2DataGenerate;
|
||||
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.CodeModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.loader.SaClientModel;
|
||||
import cn.dev33.satoken.oauth2.data.model.request.RequestAuthModel;
|
||||
import cn.dev33.satoken.oauth2.error.SaOAuth2ErrorCode;
|
||||
import cn.dev33.satoken.oauth2.exception.SaOAuth2Exception;
|
||||
import cn.dev33.satoken.oauth2.processor.SaOAuth2ServerProcessor;
|
||||
import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy;
|
||||
import cn.dev33.satoken.oauth2.template.SaOAuth2Template;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -54,20 +56,26 @@ public class SaOAuth2ServerH5Controller {
|
||||
// 3、构建请求 Model
|
||||
RequestAuthModel ra = SaOAuth2Manager.getDataResolver().readRequestAuthModel(req, loginId);
|
||||
|
||||
// 4、校验:重定向域名是否合法
|
||||
// 4、开发者自定义的授权前置检查
|
||||
SaOAuth2Strategy.instance.userAuthorizeClientCheck.run(ra.loginId, ra.clientId);
|
||||
|
||||
// 5、校验:重定向域名是否合法
|
||||
oauth2Template.checkRedirectUri(ra.clientId, ra.redirectUri);
|
||||
|
||||
// 5、校验:此次申请的Scope,该Client是否已经签约
|
||||
// 6、校验:此次申请的Scope,该Client是否已经签约
|
||||
oauth2Template.checkContractScope(ra.clientId, ra.scopes);
|
||||
|
||||
// 6、判断:如果此次申请的Scope,该用户尚未授权,则转到授权页面
|
||||
// 7、判断:如果此次申请的Scope,该用户尚未授权,则转到授权页面
|
||||
boolean isNeedCarefulConfirm = oauth2Template.isNeedCarefulConfirm(ra.loginId, ra.clientId, ra.scopes);
|
||||
if(isNeedCarefulConfirm) {
|
||||
// code=411,需要用户手动确认授权
|
||||
return SaResult.get(411, "need confirm", null);
|
||||
SaClientModel cm = oauth2Template.checkClientModel(ra.clientId);
|
||||
if( ! cm.getIsAutoConfirm()) {
|
||||
// code=411,需要用户手动确认授权
|
||||
return SaResult.get(411, "need confirm", null);
|
||||
}
|
||||
}
|
||||
|
||||
// 7、判断授权类型,重定向到不同地址
|
||||
// 8、判断授权类型,重定向到不同地址
|
||||
// 如果是 授权码式,则:开始重定向授权,下放code
|
||||
if(SaOAuth2Consts.ResponseType.code.equals(ra.responseType)) {
|
||||
CodeModel codeModel = dataGenerate.generateCode(ra);
|
||||
|
@ -0,0 +1,108 @@
|
||||
package com.pj.test;
|
||||
|
||||
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
|
||||
import cn.dev33.satoken.oauth2.template.SaOAuth2Util;
|
||||
import cn.dev33.satoken.util.SaResult;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 测试 OAuth2 相关 token 增删查
|
||||
*
|
||||
* @author click33
|
||||
* @since 2024/8/25
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/test")
|
||||
public class Test2Controller {
|
||||
|
||||
// 测试:查询全部 Access-Token --- http://localhost:8000/test/getAccessTokenValueList?clientId=1001&loginId=10001
|
||||
@RequestMapping("/getAccessTokenValueList")
|
||||
public SaResult getAccessTokenValueList(String clientId, long loginId) {
|
||||
List<String> accessTokenValueList = SaOAuth2Util.getAccessTokenValueList(clientId, loginId);
|
||||
return SaResult.data(accessTokenValueList);
|
||||
}
|
||||
|
||||
// 测试:查询全部 Access-Token, 带过期时间 --- http://localhost:8000/test/getAccessTokenIndexMap?clientId=1001&loginId=10001
|
||||
@RequestMapping("/getAccessTokenIndexMap")
|
||||
public SaResult getAccessTokenIndexMap(String clientId, long loginId) {
|
||||
Map<String, Long> accessTokenIndexMap = SaOAuth2Manager.getDao().getAccessTokenIndexMap_FromAdjustAfter(clientId, loginId);
|
||||
return SaResult.data(accessTokenIndexMap);
|
||||
}
|
||||
|
||||
// 测试:回收指定 Access-Token --- http://localhost:8000/test/revokeAccessToken?access_token=xxxxxxxxxx
|
||||
@RequestMapping("/revokeAccessToken")
|
||||
public SaResult revokeAccessToken(String access_token) {
|
||||
SaOAuth2Util.revokeAccessToken(access_token);
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
// 测试:回收全部 Access-Token --- http://localhost:8000/test/revokeAccessTokenByIndex?clientId=1001&loginId=10001
|
||||
@RequestMapping("/revokeAccessTokenByIndex")
|
||||
public SaResult revokeAccessTokenByIndex(String clientId, long loginId) {
|
||||
SaOAuth2Util.revokeAccessTokenByIndex(clientId, loginId);
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
|
||||
// 测试:查询全部 Refresh-Token --- http://localhost:8000/test/getRefreshTokenValueList?clientId=1001&loginId=10001
|
||||
@RequestMapping("/getRefreshTokenValueList")
|
||||
public SaResult getRefreshTokenValueList(String clientId, long loginId) {
|
||||
List<String> refreshTokenValueList = SaOAuth2Util.getRefreshTokenValueList(clientId, loginId);
|
||||
return SaResult.data(refreshTokenValueList);
|
||||
}
|
||||
|
||||
// 测试:查询全部 Refresh-Token, 带过期时间 --- http://localhost:8000/test/getRefreshTokenIndexMap?clientId=1001&loginId=10001
|
||||
@RequestMapping("/getRefreshTokenIndexMap")
|
||||
public SaResult getRefreshTokenIndexMap(String clientId, long loginId) {
|
||||
Map<String, Long> refreshTokenIndexMap = SaOAuth2Manager.getDao().getRefreshTokenIndexMap_FromAdjustAfter(clientId, loginId);
|
||||
return SaResult.data(refreshTokenIndexMap);
|
||||
}
|
||||
|
||||
// 测试:回收指定 Refresh-Token --- http://localhost:8000/test/revokeRefreshToken?refresh_token=xxxxxxxxxx
|
||||
@RequestMapping("/revokeRefreshToken")
|
||||
public SaResult revokeRefreshToken(String refresh_token) {
|
||||
SaOAuth2Util.revokeRefreshToken(refresh_token);
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
// 测试:回收全部 Refresh-Token --- http://localhost:8000/test/revokeRefreshTokenByIndex?clientId=1001&loginId=10001
|
||||
@RequestMapping("/revokeRefreshTokenByIndex")
|
||||
public SaResult revokeRefreshTokenByIndex(String clientId, long loginId) {
|
||||
SaOAuth2Util.revokeRefreshTokenByIndex(clientId, loginId);
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
|
||||
// 测试:查询全部 Client-Token --- http://localhost:8000/test/getClientTokenValueList?clientId=1001
|
||||
@RequestMapping("/getClientTokenValueList")
|
||||
public SaResult getClientTokenValueList(String clientId) {
|
||||
List<String> clientTokenValueList = SaOAuth2Util.getClientTokenValueList(clientId);
|
||||
return SaResult.data(clientTokenValueList);
|
||||
}
|
||||
|
||||
// 测试:查询全部 Client-Token, 带过期时间 --- http://localhost:8000/test/getClientTokenIndexMap?clientId=1001&loginId=10001
|
||||
@RequestMapping("/getClientTokenIndexMap")
|
||||
public SaResult getClientTokenIndexMap(String clientId, long loginId) {
|
||||
Map<String, Long> rlientTokenIndexMap = SaOAuth2Manager.getDao().getClientTokenIndexMap_FromAdjustAfter(clientId, loginId);
|
||||
return SaResult.data(rlientTokenIndexMap);
|
||||
}
|
||||
|
||||
// 测试:回收指定 Client-Token --- http://localhost:8000/test/revokeClientToken?client_token=xxxxxxxxxxx
|
||||
@RequestMapping("/revokeClientToken")
|
||||
public SaResult revokeClientToken(String client_token) {
|
||||
SaOAuth2Util.revokeClientToken(client_token);
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
// 测试:回收全部 Client-Token --- http://localhost:8000/test/revokeClientTokenByIndex?clientId=1001
|
||||
@RequestMapping("/revokeClientTokenByIndex")
|
||||
public SaResult revokeClientTokenByIndex(String clientId) {
|
||||
SaOAuth2Util.revokeClientTokenByIndex(clientId);
|
||||
return SaResult.ok();
|
||||
}
|
||||
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -10,13 +10,13 @@
|
||||
<parent>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-parent</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<version>3.2.1</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
</properties>
|
||||
|
@ -10,7 +10,7 @@
|
||||
<parent>
|
||||
<groupId>org.noear</groupId>
|
||||
<artifactId>solon-parent</artifactId>
|
||||
<version>3.0.4</version>
|
||||
<version>3.2.1</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
<java.version>17</java.version>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.traget>17</maven.compiler.traget>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
</properties>
|
||||
@ -51,6 +51,13 @@
|
||||
<version>${sa-token.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token json 序列化器组件:snack3 实现 -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-snack3</artifactId>
|
||||
<version>${sa-token.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- hutool工具类,用来生成雪花算法唯一id -->
|
||||
<!-- <dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
<java.run.main.class>com.pj.SaTokenApplication</java.run.main.class>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
<!-- 定义 Sa-Token 版本号 -->
|
||||
<properties>
|
||||
<sa-token.version>1.42.0</sa-token.version>
|
||||
<sa-token.version>1.44.0</sa-token.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user