From a72ba8379b4a49a8a3219a4759f91f9d41babb28 Mon Sep 17 00:00:00 2001 From: click33 <2393584716@qq.com> Date: Sun, 30 Apr 2023 17:54:22 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=BE=AA=E7=8E=AF=E7=94=9F?= =?UTF-8?q?=E6=88=90=20token=20=E7=9A=84=E7=AE=97=E6=B3=95=EF=BC=8C?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E7=A1=AE=E4=BF=9D=20Token=20=E7=9A=84?= =?UTF-8?q?=E5=94=AF=E4=B8=80=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dev33/satoken/config/SaTokenConfig.java | 86 +++++-------------- .../fun/SaGenerateUniqueTokenFunction.java | 31 +++++++ .../java/cn/dev33/satoken/stp/StpLogic.java | 33 ++++++- .../cn/dev33/satoken/strategy/SaStrategy.java | 75 +++++++++++----- .../java/cn/dev33/satoken/util/SaFoxUtil.java | 14 +-- .../java/com/pj/SaTokenDemoApplication.java | 3 +- .../main/java/com/pj/test/TestController.java | 2 +- .../src/main/resources/application.yml | 2 +- 8 files changed, 146 insertions(+), 100 deletions(-) create mode 100644 sa-token-core/src/main/java/cn/dev33/satoken/fun/SaGenerateUniqueTokenFunction.java diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java b/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java index be77d923..e0ff46f9 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/config/SaTokenConfig.java @@ -39,9 +39,13 @@ public class SaTokenConfig implements Serializable { */ private int maxLoginCount = 12; + /** 在每次创建 token 时的最高循环次数,用于保证 token 唯一性(-1=不循环尝试,直接使用) */ + private int maxTryTimes = 12; + /** 是否尝试从请求体里读取token */ private Boolean isReadBody = true; + /** 是否尝试从header里读取token */ private Boolean isReadHeader = true; @@ -205,6 +209,22 @@ public class SaTokenConfig implements Serializable { return this; } + /** + * @return 在每次创建 token 时的最高循环次数,用于保证 token 唯一性(-1=不循环尝试,直接使用) + */ + public int getMaxTryTimes() { + return maxTryTimes; + } + + /** + * @param maxTryTimes 在每次创建 token 时的最高循环次数,用于保证 token 唯一性(-1=不循环尝试,直接使用) + * @return 对象自身 + */ + public SaTokenConfig setMaxTryTimes(int maxTryTimes) { + this.maxTryTimes = maxTryTimes; + return this; + } + /** * @return 是否尝试从请求体里读取token */ @@ -411,7 +431,7 @@ public class SaTokenConfig implements Serializable { * @param logLevelInt 日志等级 int 值(1=trace、2=debug、3=info、4=warn、5=error、6=fatal) * @return 对象自身 */ - public SaTokenConfig setLogLeveInt(int logLevelInt) { + public SaTokenConfig setLogLevelInt(int logLevelInt) { this.logLevelInt = logLevelInt; this.logLevel = SaFoxUtil.translateLogLevelToString(logLevelInt); return this; @@ -521,7 +541,8 @@ public class SaTokenConfig implements Serializable { + ", activityTimeout=" + activityTimeout + ", isConcurrent=" + isConcurrent + ", isShare=" + isShare - + ", maxLoginCount=" + maxLoginCount + + ", maxLoginCount=" + maxLoginCount + + ", maxTryTimes=" + maxTryTimes + ", isReadBody=" + isReadBody + ", isReadHeader=" + isReadHeader + ", isReadCookie=" + isReadCookie @@ -544,65 +565,4 @@ public class SaTokenConfig implements Serializable { + "]"; } - - /** - *
参数 [元素名称, 最大尝试次数, 创建 token 函数, 检查 token 函数] + */ + public SaGenerateUniqueTokenFunction generateUniqueToken = (elementName, maxTryTimes, createTokenFunction, checkTokenFunction) -> { - // - // 重写策略 set连缀风格 - // - + // 为方便叙述,以下代码注释均假设在处理生成 token 的场景,但实际上本方法也可能被用于生成 code、ticket 等 + + // 循环生成 + for (int i = 1; ; i++) { + // 生成 token + String token = createTokenFunction.get(); + + // 如果 maxTryTimes == -1,表示不做唯一性验证,直接返回 + if (maxTryTimes == -1) { + return token; + } + + // 如果 token 在DB库查询不到数据,说明是个可用的全新 token,直接返回 + if (checkTokenFunction.apply(token)) { + return token; + } + + // 如果已经循环了 maxTryTimes 次,仍然没有创建出可用的 token,那么抛出异常 + if (i >= maxTryTimes) { + throw new SaTokenException(elementName + " 生成失败,已尝试" + i + "次,生成算法过于简单或资源池已耗尽"); + } + } + }; + + + // ----------------------- 重写策略 set连缀风格 /** * 重写创建 Token 的策略 @@ -276,5 +299,17 @@ public final class SaStrategy { this.isAnnotationPresent = isAnnotationPresent; return this; } - + + /** + * 生成唯一式 token 的算法 + *
参数 [元素名称, 最大尝试次数, 创建 token 函数, 检查 token 函数] + * + * @param generateUniqueToken / + * @return 对象自身 + */ + public SaStrategy setGenerateUniqueToken(SaGenerateUniqueTokenFunction generateUniqueToken) { + this.generateUniqueToken = generateUniqueToken; + return this; + } + } diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java index 40edc4d0..4dc0509f 100644 --- a/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java +++ b/sa-token-core/src/main/java/cn/dev33/satoken/util/SaFoxUtil.java @@ -1,5 +1,8 @@ package cn.dev33.satoken.util; +import cn.dev33.satoken.error.SaErrorCode; +import cn.dev33.satoken.exception.SaTokenException; + import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; @@ -8,19 +11,10 @@ import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.Iterator; -import java.util.List; +import java.util.*; import java.util.concurrent.ThreadLocalRandom; import java.util.regex.Pattern; -import cn.dev33.satoken.error.SaErrorCode; -import cn.dev33.satoken.exception.SaTokenException; - /** * Sa-Token 内部工具类 * diff --git a/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/SaTokenDemoApplication.java b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/SaTokenDemoApplication.java index 4f5e4467..7c01ff54 100644 --- a/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/SaTokenDemoApplication.java +++ b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/SaTokenDemoApplication.java @@ -1,10 +1,9 @@ package com.pj; +import cn.dev33.satoken.SaManager; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import cn.dev33.satoken.SaManager; - /** * Sa-Token整合SpringBoot 示例,整合redis * @author kong diff --git a/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/TestController.java b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/TestController.java index d0aa2580..308bcaa8 100644 --- a/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/TestController.java +++ b/sa-token-demo/sa-token-demo-springboot-redis/src/main/java/com/pj/test/TestController.java @@ -17,7 +17,7 @@ public class TestController { // 测试 浏览器访问: http://localhost:8081/test/test @RequestMapping("test") public SaResult test() { - System.out.println("------------进来了"); + System.out.println("------------进来了"); return SaResult.ok(); } diff --git a/sa-token-demo/sa-token-demo-springboot-redis/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-springboot-redis/src/main/resources/application.yml index 3a41ae12..fdb03d91 100644 --- a/sa-token-demo/sa-token-demo-springboot-redis/src/main/resources/application.yml +++ b/sa-token-demo/sa-token-demo-springboot-redis/src/main/resources/application.yml @@ -18,7 +18,7 @@ sa-token: token-style: uuid # 是否输出操作日志 is-log: true - + spring: # redis配置 redis: