From a5b65fb30e5040ee2d2e43ab04275c2296527e1f Mon Sep 17 00:00:00 2001
From: click33 <2393584716@qq.com>
Date: Fri, 11 Jun 2021 01:05:33 +0800
Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E5=90=88=20jwt=20=E4=B8=B4=E6=97=B6?=
=?UTF-8?q?=E4=BB=A4=E7=89=8C=E9=89=B4=E6=9D=83?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../main/java/cn/dev33/satoken/SaManager.java | 6 +-
.../dev33/satoken/config/SaTokenConfig.java | 28 ++++-
.../dev33/satoken/temp/SaTempDefaultImpl.java | 10 ++
.../dev33/satoken/temp/SaTempInterface.java | 9 +-
.../temp/SaTempInterfaceDefaultImpl.java | 10 --
.../cn/dev33/satoken/temp/SaTempUtil.java | 2 +-
.../sa-token-demo-springboot/pom.xml | 2 +-
sa-token-doc/doc/start/download.md | 4 +-
sa-token-doc/doc/use/config.md | 1 +
sa-token-plugin/pom.xml | 1 +
sa-token-plugin/sa-token-temp-jwt/.gitignore | 12 ++
sa-token-plugin/sa-token-temp-jwt/pom.xml | 40 ++++++
.../cn/dev33/satoken/temp/jwt/SaJwtUtil.java | 114 ++++++++++++++++++
.../dev33/satoken/temp/jwt/SaTempForJwt.java | 51 ++++++++
.../main/resources/META-INF/spring.factories | 1 +
.../spring/SaTokenSpringAutowired.java | 11 ++
.../cn/dev33/satoken/solon/XPluginImp.java | 14 ++-
.../spring/SaTokenSpringAutowired.java | 11 ++
.../pj/test/SaTokenSpringBootStarterTest.java | 1 -
19 files changed, 304 insertions(+), 24 deletions(-)
create mode 100644 sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempDefaultImpl.java
delete mode 100644 sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempInterfaceDefaultImpl.java
create mode 100644 sa-token-plugin/sa-token-temp-jwt/.gitignore
create mode 100644 sa-token-plugin/sa-token-temp-jwt/pom.xml
create mode 100644 sa-token-plugin/sa-token-temp-jwt/src/main/java/cn/dev33/satoken/temp/jwt/SaJwtUtil.java
create mode 100644 sa-token-plugin/sa-token-temp-jwt/src/main/java/cn/dev33/satoken/temp/jwt/SaTempForJwt.java
create mode 100644 sa-token-plugin/sa-token-temp-jwt/src/main/resources/META-INF/spring.factories
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/SaManager.java b/sa-token-core/src/main/java/cn/dev33/satoken/SaManager.java
index 9b9d1e38..a7b7e770 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/SaManager.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/SaManager.java
@@ -19,7 +19,7 @@ import cn.dev33.satoken.stp.StpInterfaceDefaultImpl;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.temp.SaTempInterface;
-import cn.dev33.satoken.temp.SaTempInterfaceDefaultImpl;
+import cn.dev33.satoken.temp.SaTempDefaultImpl;
import cn.dev33.satoken.util.SaFoxUtil;
/**
@@ -146,7 +146,7 @@ public class SaManager {
}
/**
- * 临时验证模块 Bean
+ * 临时令牌验证模块 Bean
*/
private static SaTempInterface saTemp;
public static void setSaTemp(SaTempInterface saTemp) {
@@ -156,7 +156,7 @@ public class SaManager {
if (saTemp == null) {
synchronized (SaManager.class) {
if (saTemp == null) {
- setSaTemp(new SaTempInterfaceDefaultImpl());
+ setSaTemp(new SaTempDefaultImpl());
}
}
}
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 af29cd17..b2c45e67 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
@@ -61,6 +61,11 @@ public class SaTokenConfig {
/** 是否打印操作日志 */
private Boolean isLog = false;
+ /**
+ * jwt秘钥 (只有集成 sa-token-temp-jwt 模块时此参数才会生效)
+ */
+ private String jwtSecretKey;
+
/**
* @return token名称 (同时也是cookie名称)
@@ -315,6 +320,7 @@ public class SaTokenConfig {
/**
* @param isLog 是否打印操作日志
+ * @return 对象自身
*/
public SaTokenConfig setIsLog(Boolean isLog) {
this.isLog = isLog;
@@ -322,7 +328,23 @@ public class SaTokenConfig {
}
/**
- * toString()
+ * @return jwt秘钥 (只有集成 sa-token-temp-jwt 模块时此参数才会生效)
+ */
+ public String getJwtSecretKey() {
+ return jwtSecretKey;
+ }
+
+ /**
+ * @param jwtSecretKey jwt秘钥 (只有集成 sa-token-temp-jwt 模块时此参数才会生效)
+ * @return 对象自身
+ */
+ public SaTokenConfig setJwtSecretKey(String jwtSecretKey) {
+ this.jwtSecretKey = jwtSecretKey;
+ return this;
+ }
+
+ /**
+ * toString()
*/
@Override
public String toString() {
@@ -331,9 +353,11 @@ public class SaTokenConfig {
+ isReadBody + ", isReadHead=" + isReadHead + ", isReadCookie=" + isReadCookie + ", tokenStyle="
+ tokenStyle + ", dataRefreshPeriod=" + dataRefreshPeriod + ", tokenSessionCheckLogin="
+ tokenSessionCheckLogin + ", autoRenew=" + autoRenew + ", cookieDomain=" + cookieDomain
- + ", tokenPrefix=" + tokenPrefix + ", isV=" + isV + ", isLog=" + isLog + "]";
+ + ", tokenPrefix=" + tokenPrefix + ", isV=" + isV + ", isLog=" + isLog + ", jwtSecretKey="
+ + jwtSecretKey + "]";
}
+
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempDefaultImpl.java b/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempDefaultImpl.java
new file mode 100644
index 00000000..e0ec0cbb
--- /dev/null
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempDefaultImpl.java
@@ -0,0 +1,10 @@
+package cn.dev33.satoken.temp;
+
+/**
+ * Sa-Token 临时令牌验证模块 默认实现类
+ * @author kong
+ *
+ */
+public class SaTempDefaultImpl implements SaTempInterface {
+
+}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempInterface.java b/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempInterface.java
index e6135e22..e2a01f19 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempInterface.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempInterface.java
@@ -4,7 +4,7 @@ import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.util.SaFoxUtil;
/**
- * Sa-Token 临时验证模块接口
+ * Sa-Token 临时令牌验证模块接口
* @author kong
*
*/
@@ -69,4 +69,11 @@ public interface SaTempInterface {
return SaManager.getConfig().getTokenName() + ":temp-token:" + token;
}
+ /**
+ * @return jwt秘钥 (只有集成 sa-token-temp-jwt 模块时此参数才会生效)
+ */
+ public default String getJwtSecretKey() {
+ return null;
+ }
+
}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempInterfaceDefaultImpl.java b/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempInterfaceDefaultImpl.java
deleted file mode 100644
index ccf3ec95..00000000
--- a/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempInterfaceDefaultImpl.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package cn.dev33.satoken.temp;
-
-/**
- * Sa-Token 临时验证模块 逻辑
- * @author kong
- *
- */
-public class SaTempInterfaceDefaultImpl implements SaTempInterface {
-
-}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempUtil.java b/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempUtil.java
index f5752d59..5c7e4fa9 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempUtil.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/temp/SaTempUtil.java
@@ -3,7 +3,7 @@ package cn.dev33.satoken.temp;
import cn.dev33.satoken.SaManager;
/**
- * Sa-Token 临时验证模块
+ * Sa-Token 临时验证令牌模块
* @author kong
*
*/
diff --git a/sa-token-demo/sa-token-demo-springboot/pom.xml b/sa-token-demo/sa-token-demo-springboot/pom.xml
index 991dca39..a0333a56 100644
--- a/sa-token-demo/sa-token-demo-springboot/pom.xml
+++ b/sa-token-demo/sa-token-demo-springboot/pom.xml
@@ -37,7 +37,7 @@
sa-token-spring-boot-starter
${sa-token-version}
-
+
sa-token-quick-login
+ sa-token-temp-jwt
\ No newline at end of file
diff --git a/sa-token-plugin/sa-token-temp-jwt/.gitignore b/sa-token-plugin/sa-token-temp-jwt/.gitignore
new file mode 100644
index 00000000..f56feec7
--- /dev/null
+++ b/sa-token-plugin/sa-token-temp-jwt/.gitignore
@@ -0,0 +1,12 @@
+target/
+
+node_modules/
+bin/
+.settings/
+unpackage/
+.classpath
+.project
+
+.factorypath
+
+.idea/
\ No newline at end of file
diff --git a/sa-token-plugin/sa-token-temp-jwt/pom.xml b/sa-token-plugin/sa-token-temp-jwt/pom.xml
new file mode 100644
index 00000000..2e5b776b
--- /dev/null
+++ b/sa-token-plugin/sa-token-temp-jwt/pom.xml
@@ -0,0 +1,40 @@
+
+
+ 4.0.0
+
+
+ cn.dev33
+ sa-token-plugin
+ 1.19.0
+
+ jar
+
+ sa-token-temp-jwt
+ sa-token-temp-jwt
+ sa-token-temp-jwt
+
+
+
+
+ cn.dev33
+ sa-token-core
+ ${sa-token-version}
+
+
+
+ io.jsonwebtoken
+ jjwt
+ 0.9.1
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ 2.0.0.RELEASE
+ true
+
+
+
+
diff --git a/sa-token-plugin/sa-token-temp-jwt/src/main/java/cn/dev33/satoken/temp/jwt/SaJwtUtil.java b/sa-token-plugin/sa-token-temp-jwt/src/main/java/cn/dev33/satoken/temp/jwt/SaJwtUtil.java
new file mode 100644
index 00000000..3c4c0297
--- /dev/null
+++ b/sa-token-plugin/sa-token-temp-jwt/src/main/java/cn/dev33/satoken/temp/jwt/SaJwtUtil.java
@@ -0,0 +1,114 @@
+package cn.dev33.satoken.temp.jwt;
+
+import cn.dev33.satoken.dao.SaTokenDao;
+import cn.dev33.satoken.exception.SaTokenException;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.JwtBuilder;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+
+/**
+ * jwt操作工具类
+ * @author kong
+ *
+ */
+public class SaJwtUtil {
+
+ /**
+ * key: value
+ */
+ public static final String KEY_VALUE = "value";
+
+ /**
+ * key: 有效期 (时间戳)
+ */
+ public static final String KEY_EFF = "eff";
+
+ /** 当有效期被设为此值时,代表永不过期 */
+ public static final long NEVER_EXPIRE = SaTokenDao.NEVER_EXPIRE;
+
+ /**
+ * 根据指定值创建 jwt-token
+ * @param value 要保存的值
+ * @param timeout token有效期 (单位 秒)
+ * @param keyt 秘钥
+ * @return jwt-token
+ */
+ public static String createToken(Object value, long timeout, String keyt) {
+ // 计算eff有效期
+ long eff = timeout;
+ if(timeout != NEVER_EXPIRE) {
+ eff = timeout * 1000 + System.currentTimeMillis();
+ }
+ // 在这里你可以使用官方提供的claim方法构建载荷,也可以使用setPayload自定义载荷,但是两者不可一起使用
+ JwtBuilder builder = Jwts.builder()
+ // .setHeaderParam("typ", "JWT")
+ .claim(KEY_VALUE, value)
+ .claim(KEY_EFF, eff)
+ .signWith(SignatureAlgorithm.HS256, keyt.getBytes());
+ // 生成jwt-token
+ return builder.compact();
+ }
+
+ /**
+ * 从一个 jwt-token 解析出载荷
+ * @param jwtToken JwtToken值
+ * @param keyt 秘钥
+ * @return Claims对象
+ */
+ public static Claims parseToken(String jwtToken, String keyt) {
+ // 解析出载荷
+ Claims claims = Jwts.parser()
+ .setSigningKey(keyt.getBytes())
+ .parseClaimsJws(jwtToken).getBody();
+ // 返回
+ return claims;
+ }
+
+ /**
+ * 从一个 jwt-token 解析出载荷, 并取出数据
+ * @param jwtToken JwtToken值
+ * @param keyt 秘钥
+ * @return 值
+ */
+ public static Object getValue(String jwtToken, String keyt) {
+ // 取出数据
+ Claims claims = parseToken(jwtToken, keyt);
+
+ // 验证是否超时
+ Long eff = claims.get(KEY_EFF, Long.class);
+ if((eff == null || eff < System.currentTimeMillis()) && eff != NEVER_EXPIRE) {
+ throw new SaTokenException("Token已超时");
+ }
+
+ // 获取数据
+ return claims.get(KEY_VALUE);
+ }
+
+ /**
+ * 从一个 jwt-token 解析出载荷, 并取出其剩余有效期
+ * @param jwtToken JwtToken值
+ * @param keyt 秘钥
+ * @return 值
+ */
+ public static long getTimeout(String jwtToken, String keyt) {
+ // 取出数据
+ Claims claims = parseToken(jwtToken, keyt);
+
+ // 验证是否超时
+ Long eff = claims.get(KEY_EFF, Long.class);
+
+ // 永不过期
+ if(eff == NEVER_EXPIRE) {
+ return NEVER_EXPIRE;
+ }
+ // 已经超时
+ if(eff == null || eff < System.currentTimeMillis()) {
+ return SaTokenDao.NOT_VALUE_EXPIRE;
+ }
+
+ // 计算timeout
+ return (eff - System.currentTimeMillis()) / 1000;
+ }
+
+}
diff --git a/sa-token-plugin/sa-token-temp-jwt/src/main/java/cn/dev33/satoken/temp/jwt/SaTempForJwt.java b/sa-token-plugin/sa-token-temp-jwt/src/main/java/cn/dev33/satoken/temp/jwt/SaTempForJwt.java
new file mode 100644
index 00000000..60c157fc
--- /dev/null
+++ b/sa-token-plugin/sa-token-temp-jwt/src/main/java/cn/dev33/satoken/temp/jwt/SaTempForJwt.java
@@ -0,0 +1,51 @@
+package cn.dev33.satoken.temp.jwt;
+
+import cn.dev33.satoken.SaManager;
+import cn.dev33.satoken.exception.SaTokenException;
+import cn.dev33.satoken.temp.SaTempInterface;
+import cn.dev33.satoken.util.SaFoxUtil;
+
+/**
+ * Sa-Token 临时令牌验证模块接口 JWT实现类
+ * @author kong
+ *
+ */
+public class SaTempForJwt implements SaTempInterface {
+
+ /**
+ * 根据value创建一个token
+ */
+ public String createToken(Object value, long timeout) {
+ String token = SaJwtUtil.createToken(value, timeout, getJwtSecretKey());
+ return token;
+ }
+
+ /**
+ * 解析token获取value
+ */
+ public Object parseToken(String token) {
+ Object value = SaJwtUtil.getValue(token, getJwtSecretKey());
+ return value;
+ }
+
+ /**
+ * 返回指定token的剩余有效期,单位:秒
+ */
+ public long getTimeout(String token) {
+ long timeout = SaJwtUtil.getTimeout(token, getJwtSecretKey());
+ return timeout;
+ }
+
+ /**
+ * 获取jwt秘钥
+ * @return jwt秘钥
+ */
+ public String getJwtSecretKey() {
+ String jwtSecretKey = SaManager.getConfig().getJwtSecretKey();
+ if(SaFoxUtil.isEmpty(jwtSecretKey)) {
+ throw new SaTokenException("请配置:jwtSecretKey");
+ }
+ return jwtSecretKey;
+ }
+
+}
diff --git a/sa-token-plugin/sa-token-temp-jwt/src/main/resources/META-INF/spring.factories b/sa-token-plugin/sa-token-temp-jwt/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..0c16a1f2
--- /dev/null
+++ b/sa-token-plugin/sa-token-temp-jwt/src/main/resources/META-INF/spring.factories
@@ -0,0 +1 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.dev33.satoken.temp.jwt.SaTempForJwt
\ No newline at end of file
diff --git a/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/SaTokenSpringAutowired.java b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/SaTokenSpringAutowired.java
index 4ccb0f99..e3fa1613 100644
--- a/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/SaTokenSpringAutowired.java
+++ b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/SaTokenSpringAutowired.java
@@ -15,6 +15,7 @@ import cn.dev33.satoken.context.SaTokenContextForThreadLocal;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.stp.StpInterface;
+import cn.dev33.satoken.temp.SaTempInterface;
/**
* 利用spring的自动装配来加载开发者重写的Bean
@@ -113,6 +114,16 @@ public class SaTokenSpringAutowired {
public void setSaTokenListener(SaTokenListener saTokenListener) {
SaManager.setSaTokenListener(saTokenListener);
}
+
+ /**
+ * 注入临时令牌验证模块 Bean
+ *
+ * @param saTemp saTemp对象
+ */
+ @Autowired(required = false)
+ public void setSaTemp(SaTempInterface saTemp) {
+ SaManager.setSaTemp(saTemp);
+ }
/**
* 利用自动注入特性,获取Spring框架内部使用的路由匹配器
diff --git a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/XPluginImp.java b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/XPluginImp.java
index 64892b73..1fe41a55 100644
--- a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/XPluginImp.java
+++ b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/XPluginImp.java
@@ -16,6 +16,7 @@ import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.solon.integration.SaContextForSolon;
import cn.dev33.satoken.solon.integration.SaTokenMethodInterceptor;
import cn.dev33.satoken.stp.StpInterface;
+import cn.dev33.satoken.temp.SaTempInterface;
/**
* @author noear
@@ -39,25 +40,30 @@ public class XPluginImp implements Plugin {
//注入容器交互Bean
SaManager.setSaTokenContext(new SaContextForSolon());
- //注入侦听器Bean
+ // 注入侦听器 Bean
Aop.getAsyn(SaTokenListener.class, bw->{
SaManager.setSaTokenListener(bw.raw());
});
- //注入框架行为Bean
+ // 注入框架行为 Bean
Aop.getAsyn(SaTokenAction.class, bw->{
SaManager.setSaTokenAction(bw.raw());
});
- //注入权限认证Bean
+ // 注入权限认证 Bean
Aop.getAsyn(StpInterface.class, bw->{
SaManager.setStpInterface(bw.raw());
});
- //注入持久化Bean
+ // 注入持久化 Bean
Aop.getAsyn(SaTokenDao.class, bw->{
SaManager.setSaTokenDao(bw.raw());
});
+
+ // 临时令牌验证模块 Bean
+ Aop.getAsyn(SaTempInterface.class, bw->{
+ SaManager.setSaTemp(bw.raw());
+ });
}
}
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaTokenSpringAutowired.java b/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaTokenSpringAutowired.java
index 2d313e63..117f5534 100644
--- a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaTokenSpringAutowired.java
+++ b/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaTokenSpringAutowired.java
@@ -14,6 +14,7 @@ import cn.dev33.satoken.context.SaTokenContext;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.stp.StpInterface;
+import cn.dev33.satoken.temp.SaTempInterface;
/**
* 利用spring的自动装配来加载开发者重写的Bean
@@ -105,6 +106,16 @@ public class SaTokenSpringAutowired {
SaManager.setSaTokenListener(saTokenListener);
}
+ /**
+ * 注入临时令牌验证模块 Bean
+ *
+ * @param saTemp saTemp对象
+ */
+ @Autowired(required = false)
+ public void setSaTemp(SaTempInterface saTemp) {
+ SaManager.setSaTemp(saTemp);
+ }
+
/**
* 利用自动注入特性,获取Spring框架内部使用的路由匹配器
*
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/SaTokenSpringBootStarterTest.java b/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/SaTokenSpringBootStarterTest.java
index 38d03358..3f7a0afd 100644
--- a/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/SaTokenSpringBootStarterTest.java
+++ b/sa-token-starter/sa-token-spring-boot-starter/src/test/java/com/pj/test/SaTokenSpringBootStarterTest.java
@@ -177,7 +177,6 @@ public class SaTokenSpringBootStarterTest {
// 解析token
String value = SaTempUtil.parseToken(token, String.class);
- System.out.println(value);
Assert.assertEquals(value, "group-1014");
// 过期时间