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 e916afb7..2d6cf4e8 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
@@ -35,7 +35,7 @@ public class SaTokenConfig implements Serializable {
/**
* 同一账号最大登录数量,-1代表不限 (只有在 isConcurrent=true, isShare=false 时此配置才有效)
*/
- private int maxLoginCount = 10;
+ private int maxLoginCount = 12;
/** 是否尝试从请求体里读取token */
private Boolean isReadBody = true;
@@ -93,11 +93,6 @@ public class SaTokenConfig implements Serializable {
*/
public SaCookieConfig cookie = new SaCookieConfig();
- /**
- * SSO单点登录配置对象
- */
- public SaSsoConfig sso = new SaSsoConfig();
-
/**
* @return token名称 (同时也是cookie名称)
@@ -439,22 +434,6 @@ public class SaTokenConfig implements Serializable {
return this;
}
- /**
- * @return SSO单点登录配置对象
- */
- public SaSsoConfig getSso() {
- return sso;
- }
-
- /**
- * @param sso SSO单点登录配置对象
- * @return 对象自身
- */
- public SaTokenConfig setSso(SaSsoConfig sso) {
- this.sso = sso;
- return this;
- }
-
/**
* @return Cookie 全局配置对象
*/
@@ -495,7 +474,6 @@ public class SaTokenConfig implements Serializable {
+ ", basic=" + basic
+ ", currDomain=" + currDomain
+ ", checkIdToken=" + checkIdToken
- + ", sso=" + sso
+ ", cookie=" + cookie
+ "]";
}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/exception/NotPermissionException.java b/sa-token-core/src/main/java/cn/dev33/satoken/exception/NotPermissionException.java
index 6ab6e0b8..0b1130b8 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/exception/NotPermissionException.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/exception/NotPermissionException.java
@@ -16,13 +16,13 @@ public class NotPermissionException extends SaTokenException {
private static final long serialVersionUID = 6806129545290130141L;
/** 权限码 */
- private String code;
+ private String permission;
/**
- * @return 获得权限码
+ * @return 获得具体缺少的权限码
*/
- public String getCode() {
- return code;
+ public String getPermission() {
+ return permission;
}
/**
@@ -39,14 +39,23 @@ public class NotPermissionException extends SaTokenException {
return loginType;
}
- public NotPermissionException(String code) {
- this(code, StpUtil.stpLogic.loginType);
+ public NotPermissionException(String permission) {
+ this(permission, StpUtil.stpLogic.loginType);
}
- public NotPermissionException(String code, String loginType) {
- super("无此权限:" + code);
- this.code = code;
+ public NotPermissionException(String permission, String loginType) {
+ super("无此权限:" + permission);
+ this.permission = permission;
this.loginType = loginType;
}
+ /**
+ *
警告:自 v1.30+ 版本起,获取异常权限码由 getCode() 更改为 getPermission(),请及时更换!
+ * @return 获得权限码
+ */
+ @Deprecated
+ public int getCode() {
+ return super.getCode();
+ }
+
}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/exception/SaExceptionCode.java b/sa-token-core/src/main/java/cn/dev33/satoken/exception/SaExceptionCode.java
new file mode 100644
index 00000000..78a8b1b5
--- /dev/null
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/exception/SaExceptionCode.java
@@ -0,0 +1,14 @@
+package cn.dev33.satoken.exception;
+
+/**
+ * 定义所有异常细分状态码
+ *
+ * @author kong
+ * @date: 2022-4-25
+ */
+public class SaExceptionCode {
+
+ /** 代表未指定异常细分状态码 */
+ public static final int CODE_UNDEFINED = -1;
+
+}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/exception/SaTokenException.java b/sa-token-core/src/main/java/cn/dev33/satoken/exception/SaTokenException.java
index 97456ef7..a5a1d71f 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/exception/SaTokenException.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/exception/SaTokenException.java
@@ -16,6 +16,22 @@ public class SaTokenException extends RuntimeException {
*/
private static final long serialVersionUID = 6806129545290130132L;
+ /**
+ * 异常细分状态码
+ */
+ private int code = SaExceptionCode.CODE_UNDEFINED;
+
+ /**
+ * 构建一个异常
+ *
+ * @param code 异常细分状态码
+ */
+ public SaTokenException(int code) {
+ super();
+ this.code = code;
+ }
+
+
/**
* 构建一个异常
*
@@ -25,6 +41,17 @@ public class SaTokenException extends RuntimeException {
super(message);
}
+ /**
+ * 构建一个异常
+ *
+ * @param code 异常细分状态码
+ * @param message 异常信息
+ */
+ public SaTokenException(int code, String message) {
+ super(message);
+ this.code = code;
+ }
+
/**
* 构建一个异常
*
@@ -44,6 +71,23 @@ public class SaTokenException extends RuntimeException {
super(message, cause);
}
+ /**
+ * @return 异常细分状态码
+ */
+ public int getCode() {
+ return code;
+ }
+
+ /**
+ * 写入异常细分状态码
+ * @param code 异常细分状态码
+ * @return 对象自身
+ */
+ public SaTokenException setCode(int code) {
+ this.code = code;
+ return this;
+ }
+
/**
* 如果flag==true,则抛出message异常
* @param flag 标记
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java
index cfd80969..14291d90 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java
+++ b/sa-token-core/src/main/java/cn/dev33/satoken/stp/StpLogic.java
@@ -320,10 +320,7 @@ public class StpLogic {
if(getConfigOfIsShare()) {
tokenValue = getTokenValueByLoginId(id, loginModel.getDeviceOrDefault());
} else {
- // 如果配置为不共享token,需要检查会话是否超出 max-login-count
- if(config.getMaxLoginCount() != -1) {
- logoutByRetainCount(id, null, config.getMaxLoginCount() - 1);
- }
+ //
}
} else {
// --- 如果不允许并发登录,则将这个账号的历史登录标记为:被顶下线
@@ -354,6 +351,11 @@ public class StpLogic {
// $$ 通知监听器,账号xxx 登录成功
SaManager.getSaTokenListener().doLogin(loginType, id, loginModel);
+
+ // 检查此账号会话数量是否超出最大值
+ if(config.getMaxLoginCount() != -1) {
+ logoutByMaxLoginCount(id, session, null, config.getMaxLoginCount());
+ }
// 返回Token
return tokenValue;
@@ -399,28 +401,11 @@ public class StpLogic {
* @param device 设备类型 (填null代表注销所有设备类型)
*/
public void logout(Object loginId, String device) {
- logoutByRetainCount(loginId, device, 0);
- }
-
- /**
- * 会话注销,根据账号id 和 设备类型 和 保留数量
- *
- * @param loginId 账号id
- * @param device 设备类型 (填null代表注销所有设备类型)
- * @param retainCount 保留最近的n次登录
- */
- public void logoutByRetainCount(Object loginId, String device, int retainCount) {
SaSession session = getSessionByLoginId(loginId, false);
if(session != null) {
- List list = session.tokenSignListCopyByDevice(device);
- // 遍历操作
- for (int i = 0; i < list.size(); i++) {
- // 只操作前n条
- if(i >= list.size() - retainCount) {
- continue;
- }
+ for (TokenSign tokenSign: session.tokenSignListCopyByDevice(device)) {
// 清理: token签名、token最后活跃时间
- String tokenValue = list.get(i).getValue();
+ String tokenValue = tokenSign.getValue();
session.removeTokenSign(tokenValue);
clearLastActivity(tokenValue);
// 删除Token-Id映射 & 清除Token-Session
@@ -433,6 +418,41 @@ public class StpLogic {
}
}
+ /**
+ * 会话注销,根据账号id 和 设备类型 和 最大同时在线数量
+ *
+ * @param loginId 账号id
+ * @param session 此账号的 Session 对象,可填写null,框架将自动获取
+ * @param device 设备类型 (填null代表注销所有设备类型)
+ * @param maxLoginCount 保留最近的几次登录
+ */
+ public void logoutByMaxLoginCount(Object loginId, SaSession session, String device, int maxLoginCount) {
+ if(session == null) {
+ session = getSessionByLoginId(loginId, false);
+ if(session == null) {
+ return;
+ }
+ }
+ List list = session.tokenSignListCopyByDevice(device);
+ // 遍历操作
+ for (int i = 0; i < list.size(); i++) {
+ // 只操作前n条
+ if(i >= list.size() - maxLoginCount) {
+ continue;
+ }
+ // 清理: token签名、token最后活跃时间
+ String tokenValue = list.get(i).getValue();
+ session.removeTokenSign(tokenValue);
+ clearLastActivity(tokenValue);
+ // 删除Token-Id映射 & 清除Token-Session
+ deleteTokenToIdMapping(tokenValue);
+ deleteTokenSession(tokenValue);
+ SaManager.getSaTokenListener().doLogout(loginType, loginId, tokenValue);
+ }
+ // 注销 Session
+ session.logoutByTokenSignCountToZero();
+ }
+
/**
* 会话注销,根据指定 Token
*
diff --git a/sa-token-demo/sa-token-demo-jwt/src/main/java/com/pj/test/GlobalException.java b/sa-token-demo/sa-token-demo-jwt/src/main/java/com/pj/test/GlobalException.java
index 42083dc6..e06c4f01 100644
--- a/sa-token-demo/sa-token-demo-jwt/src/main/java/com/pj/test/GlobalException.java
+++ b/sa-token-demo/sa-token-demo-jwt/src/main/java/com/pj/test/GlobalException.java
@@ -36,7 +36,7 @@ public class GlobalException {
aj = AjaxJson.getNotJur("无此角色:" + ee.getRole());
} else if(e instanceof NotPermissionException) { // 如果是权限异常
NotPermissionException ee = (NotPermissionException) e;
- aj = AjaxJson.getNotJur("无此权限:" + ee.getCode());
+ aj = AjaxJson.getNotJur("无此权限:" + ee.getPermission());
} else { // 普通异常, 输出:500 + 异常信息
aj = AjaxJson.getError(e.getMessage());
}
diff --git a/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/test/GlobalException.java b/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/test/GlobalException.java
index a2818a1a..75c39609 100644
--- a/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/test/GlobalException.java
+++ b/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/test/GlobalException.java
@@ -31,7 +31,7 @@ public class GlobalException implements EventListener {
aj = AjaxJson.getNotJur("无此角色:" + ee.getRole());
} else if (e instanceof NotPermissionException) { // 如果是权限异常
NotPermissionException ee = (NotPermissionException) e;
- aj = AjaxJson.getNotJur("无此权限:" + ee.getCode());
+ aj = AjaxJson.getNotJur("无此权限:" + ee.getPermission());
} else if (e instanceof DisableLoginException) { // 如果是被封禁异常
DisableLoginException ee = (DisableLoginException) e;
aj = AjaxJson.getNotJur("账号被封禁:" + ee.getDisableTime() + "秒后解封");
diff --git a/sa-token-demo/sa-token-demo-springboot/src/main/java/com/pj/current/GlobalException.java b/sa-token-demo/sa-token-demo-springboot/src/main/java/com/pj/current/GlobalException.java
index ff974d3d..8d2c254d 100644
--- a/sa-token-demo/sa-token-demo-springboot/src/main/java/com/pj/current/GlobalException.java
+++ b/sa-token-demo/sa-token-demo-springboot/src/main/java/com/pj/current/GlobalException.java
@@ -42,7 +42,7 @@ public class GlobalException {
}
else if(e instanceof NotPermissionException) { // 如果是权限异常
NotPermissionException ee = (NotPermissionException) e;
- aj = AjaxJson.getNotJur("无此权限:" + ee.getCode());
+ aj = AjaxJson.getNotJur("无此权限:" + ee.getPermission());
}
else if(e instanceof DisableLoginException) { // 如果是被封禁异常
DisableLoginException ee = (DisableLoginException) e;
diff --git a/sa-token-demo/sa-token-demo-sso-server/pom.xml b/sa-token-demo/sa-token-demo-sso-server/pom.xml
index 733ab919..3f9c467c 100644
--- a/sa-token-demo/sa-token-demo-sso-server/pom.xml
+++ b/sa-token-demo/sa-token-demo-sso-server/pom.xml
@@ -34,7 +34,14 @@
${sa-token-version}
-
+
+
+ cn.dev33
+ sa-token-sso
+ ${sa-token-version}
+
+
+
cn.dev33
sa-token-dao-redis-jackson
diff --git a/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/sso/SsoServerController.java b/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/sso/SsoServerController.java
index 2a2e8ef6..c3bab92e 100644
--- a/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/sso/SsoServerController.java
+++ b/sa-token-demo/sa-token-demo-sso-server/src/main/java/com/pj/sso/SsoServerController.java
@@ -7,7 +7,7 @@ import org.springframework.web.servlet.ModelAndView;
import com.ejlchina.okhttps.OkHttps;
-import cn.dev33.satoken.config.SaTokenConfig;
+import cn.dev33.satoken.config.SaSsoConfig;
import cn.dev33.satoken.sso.SaSsoHandle;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
@@ -34,15 +34,15 @@ public class SsoServerController {
// 配置SSO相关参数
@Autowired
- private void configSso(SaTokenConfig cfg) {
+ private void configSso(SaSsoConfig sso) {
// 配置:未登录时返回的View
- cfg.sso.setNotLoginView(() -> {
+ sso.setNotLoginView(() -> {
return new ModelAndView("sa-login.html");
});
// 配置:登录处理函数
- cfg.sso.setDoLoginHandle((name, pwd) -> {
+ sso.setDoLoginHandle((name, pwd) -> {
// 此处仅做模拟登录,真实环境应该查询数据进行登录
if("sa".equals(name) && "123456".equals(pwd)) {
StpUtil.login(10001);
@@ -52,7 +52,7 @@ public class SsoServerController {
});
// 配置 Http 请求处理器 (在模式三的单点注销功能下用到,如不需要可以注释掉)
- cfg.sso.setSendHttp(url -> {
+ sso.setSendHttp(url -> {
return OkHttps.sync(url).get().getBody().toString();
});
}
diff --git a/sa-token-demo/sa-token-demo-sso1-client/pom.xml b/sa-token-demo/sa-token-demo-sso1-client/pom.xml
index dc38ac25..70e0a4dd 100644
--- a/sa-token-demo/sa-token-demo-sso1-client/pom.xml
+++ b/sa-token-demo/sa-token-demo-sso1-client/pom.xml
@@ -34,6 +34,13 @@
${sa-token-version}
+
+
+ cn.dev33
+ sa-token-sso
+ ${sa-token-version}
+
+
cn.dev33
diff --git a/sa-token-demo/sa-token-demo-sso1-client/src/main/java/com/pj/sso/SsoClientController.java b/sa-token-demo/sa-token-demo-sso1-client/src/main/java/com/pj/sso/SsoClientController.java
index 2451c96d..da91e2a0 100644
--- a/sa-token-demo/sa-token-demo-sso1-client/src/main/java/com/pj/sso/SsoClientController.java
+++ b/sa-token-demo/sa-token-demo-sso1-client/src/main/java/com/pj/sso/SsoClientController.java
@@ -4,7 +4,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import cn.dev33.satoken.SaManager;
+import cn.dev33.satoken.sso.SaSsoManager;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
@@ -18,8 +18,8 @@ public class SsoClientController {
// SSO-Client端:首页
@RequestMapping("/")
public String index() {
- String authUrl = SaManager.getConfig().getSso().getAuthUrl();
- String solUrl = SaManager.getConfig().getSso().getSloUrl();
+ String authUrl = SaSsoManager.getConfig().getAuthUrl();
+ String solUrl = SaSsoManager.getConfig().getSloUrl();
String str = "Sa-Token SSO-Client 应用端
" +
"当前会话是否登录:" + StpUtil.isLogin() + "
" +
"登录 " +
diff --git a/sa-token-demo/sa-token-demo-sso2-client/pom.xml b/sa-token-demo/sa-token-demo-sso2-client/pom.xml
index 093bebff..944df1c7 100644
--- a/sa-token-demo/sa-token-demo-sso2-client/pom.xml
+++ b/sa-token-demo/sa-token-demo-sso2-client/pom.xml
@@ -34,6 +34,13 @@
${sa-token-version}
+
+
+ cn.dev33
+ sa-token-sso
+ ${sa-token-version}
+
+
cn.dev33
diff --git a/sa-token-demo/sa-token-demo-sso3-client/pom.xml b/sa-token-demo/sa-token-demo-sso3-client/pom.xml
index 4542ed0b..afcfaf14 100644
--- a/sa-token-demo/sa-token-demo-sso3-client/pom.xml
+++ b/sa-token-demo/sa-token-demo-sso3-client/pom.xml
@@ -34,6 +34,13 @@
${sa-token-version}
+
+
+ cn.dev33
+ sa-token-sso
+ ${sa-token-version}
+
+
cn.dev33
diff --git a/sa-token-demo/sa-token-demo-sso3-client/src/main/java/com/pj/sso/SsoClientController.java b/sa-token-demo/sa-token-demo-sso3-client/src/main/java/com/pj/sso/SsoClientController.java
index 3099353c..2c124caf 100644
--- a/sa-token-demo/sa-token-demo-sso3-client/src/main/java/com/pj/sso/SsoClientController.java
+++ b/sa-token-demo/sa-token-demo-sso3-client/src/main/java/com/pj/sso/SsoClientController.java
@@ -7,7 +7,7 @@ import org.springframework.web.bind.annotation.RestController;
import com.ejlchina.okhttps.OkHttps;
-import cn.dev33.satoken.config.SaTokenConfig;
+import cn.dev33.satoken.config.SaSsoConfig;
import cn.dev33.satoken.sso.SaSsoHandle;
import cn.dev33.satoken.sso.SaSsoUtil;
import cn.dev33.satoken.stp.StpUtil;
@@ -43,9 +43,9 @@ public class SsoClientController {
// 配置SSO相关参数
@Autowired
- private void configSso(SaTokenConfig cfg) {
+ private void configSso(SaSsoConfig sso) {
// 配置Http请求处理器
- cfg.sso.setSendHttp(url -> {
+ sso.setSendHttp(url -> {
return OkHttps.sync(url).get().getBody().toString();
});
}
diff --git a/sa-token-demo/sa-token-demo-webflux/src/main/java/com/pj/test/GlobalException.java b/sa-token-demo/sa-token-demo-webflux/src/main/java/com/pj/test/GlobalException.java
index 0d470ce0..f4ea451d 100644
--- a/sa-token-demo/sa-token-demo-webflux/src/main/java/com/pj/test/GlobalException.java
+++ b/sa-token-demo/sa-token-demo-webflux/src/main/java/com/pj/test/GlobalException.java
@@ -37,7 +37,7 @@ public class GlobalException {
aj = AjaxJson.getNotJur("无此角色:" + ee.getRole());
} else if(e instanceof NotPermissionException) { // 如果是权限异常
NotPermissionException ee = (NotPermissionException) e;
- aj = AjaxJson.getNotJur("无此权限:" + ee.getCode());
+ aj = AjaxJson.getNotJur("无此权限:" + ee.getPermission());
} else if(e instanceof DisableLoginException) { // 如果是被封禁异常
DisableLoginException ee = (DisableLoginException) e;
aj = AjaxJson.getNotJur("账号被封禁:" + ee.getDisableTime() + "秒后解封");
diff --git a/sa-token-doc/doc/use/config.md b/sa-token-doc/doc/use/config.md
index 80330f16..0f736806 100644
--- a/sa-token-doc/doc/use/config.md
+++ b/sa-token-doc/doc/use/config.md
@@ -79,7 +79,7 @@ PS:两者的区别在于:**`模式1会覆盖yml中的配置,模式2会与y
| activityTimeout | long | -1 | token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒, 默认-1 代表不限制 (例如可以设置为1800代表30分钟内无操作就过期) [参考:token有效期详解](/fun/token-timeout) |
| isConcurrent | Boolean | true | 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) |
| isShare | Boolean | true | 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) |
-| maxLoginCount | int | 10 | 同一账号最大登录数量,-1代表不限 (只有在 isConcurrent=true, isShare=false 时此配置才有效) |
+| maxLoginCount | int | 12 | 同一账号最大登录数量,-1代表不限 (只有在 isConcurrent=true, isShare=false 时此配置才有效) |
| isReadBody | Boolean | true | 是否尝试从 请求体 里读取 Token |
| isReadHead | Boolean | true | 是否尝试从 header 里读取 Token |
| isReadCookie | Boolean | true | 是否尝试从 cookie 里读取 Token |
diff --git a/sa-token-plugin/sa-token-sso/.gitignore b/sa-token-plugin/sa-token-sso/.gitignore
new file mode 100644
index 00000000..8122f47c
--- /dev/null
+++ b/sa-token-plugin/sa-token-sso/.gitignore
@@ -0,0 +1,13 @@
+target/
+
+node_modules/
+bin/
+.settings/
+unpackage/
+.classpath
+.project
+
+.factorypath
+
+.idea/
+.iml
\ No newline at end of file
diff --git a/sa-token-plugin/sa-token-sso/pom.xml b/sa-token-plugin/sa-token-sso/pom.xml
new file mode 100644
index 00000000..74c34bfe
--- /dev/null
+++ b/sa-token-plugin/sa-token-sso/pom.xml
@@ -0,0 +1,30 @@
+
+
+ 4.0.0
+
+
+ cn.dev33
+ sa-token-plugin
+ ${revision}
+ ../pom.xml
+
+ jar
+
+ sa-token-sso
+ sa-token-sso
+ sa-token realization sso
+
+
+
+
+ cn.dev33
+ sa-token-core
+ ${revision}
+
+
+
+
+
+
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/config/SaSsoConfig.java b/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/config/SaSsoConfig.java
similarity index 99%
rename from sa-token-core/src/main/java/cn/dev33/satoken/config/SaSsoConfig.java
rename to sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/config/SaSsoConfig.java
index 8af27bee..ea74ae19 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/config/SaSsoConfig.java
+++ b/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/config/SaSsoConfig.java
@@ -1,5 +1,6 @@
package cn.dev33.satoken.config;
+
import java.io.Serializable;
import java.util.function.BiFunction;
import java.util.function.Function;
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoConsts.java b/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/SaSsoConsts.java
similarity index 100%
rename from sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoConsts.java
rename to sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/SaSsoConsts.java
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoHandle.java b/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/SaSsoHandle.java
similarity index 94%
rename from sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoHandle.java
rename to sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/SaSsoHandle.java
index 98d19bb6..8d116702 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoHandle.java
+++ b/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/SaSsoHandle.java
@@ -1,13 +1,13 @@
package cn.dev33.satoken.sso;
-import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.config.SaSsoConfig;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
-import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.sso.SaSsoConsts.Api;
import cn.dev33.satoken.sso.SaSsoConsts.ParamName;
+import cn.dev33.satoken.sso.exception.SaSsoException;
+import cn.dev33.satoken.sso.exception.SaSsoExceptionCode;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaResult;
@@ -27,7 +27,7 @@ public class SaSsoHandle {
// 获取对象
SaRequest req = SaHolder.getRequest();
- SaSsoConfig cfg = SaManager.getConfig().getSso();
+ SaSsoConfig cfg = SaSsoManager.getConfig();
// ------------------ 路由分发 ------------------
@@ -68,7 +68,7 @@ public class SaSsoHandle {
// 获取对象
SaRequest req = SaHolder.getRequest();
SaResponse res = SaHolder.getResponse();
- SaSsoConfig cfg = SaManager.getConfig().getSso();
+ SaSsoConfig cfg = SaSsoManager.getConfig();
StpLogic stpLogic = SaSsoUtil.saSsoTemplate.stpLogic;
// ---------- 此处有两种情况分开处理:
@@ -98,7 +98,7 @@ public class SaSsoHandle {
public static Object ssoDoLogin() {
// 获取对象
SaRequest req = SaHolder.getRequest();
- SaSsoConfig cfg = SaManager.getConfig().getSso();
+ SaSsoConfig cfg = SaSsoManager.getConfig();
// 处理
return cfg.getDoLoginHandle().apply(req.getParam(ParamName.name), req.getParam(ParamName.pwd));
@@ -150,7 +150,7 @@ public class SaSsoHandle {
public static Object ssoServerLogout() {
// 获取对象
SaRequest req = SaHolder.getRequest();
- SaSsoConfig cfg = SaManager.getConfig().getSso();
+ SaSsoConfig cfg = SaSsoManager.getConfig();
StpLogic stpLogic = SaSsoUtil.saSsoTemplate.stpLogic;
// 获取参数
@@ -180,7 +180,7 @@ public class SaSsoHandle {
// 获取对象
SaRequest req = SaHolder.getRequest();
- SaSsoConfig cfg = SaManager.getConfig().getSso();
+ SaSsoConfig cfg = SaSsoManager.getConfig();
// ------------------ 路由分发 ------------------
@@ -216,7 +216,7 @@ public class SaSsoHandle {
// 获取对象
SaRequest req = SaHolder.getRequest();
SaResponse res = SaHolder.getResponse();
- SaSsoConfig cfg = SaManager.getConfig().getSso();
+ SaSsoConfig cfg = SaSsoManager.getConfig();
StpLogic stpLogic = SaSsoUtil.saSsoTemplate.stpLogic;
// 获取参数
@@ -249,7 +249,7 @@ public class SaSsoHandle {
return res.redirect(back);
} else {
// 如果ticket无效:
- throw new SaTokenException("无效ticket:" + ticket);
+ throw new SaSsoException("无效ticket:" + ticket).setCode(SaSsoExceptionCode.CODE_20004);
}
}
}
@@ -279,7 +279,7 @@ public class SaSsoHandle {
// 获取对象
SaRequest req = SaHolder.getRequest();
SaResponse res = SaHolder.getResponse();
- SaSsoConfig cfg = SaManager.getConfig().getSso();
+ SaSsoConfig cfg = SaSsoManager.getConfig();
StpLogic stpLogic = SaSsoUtil.saSsoTemplate.stpLogic;
// 如果未登录,则无需注销
@@ -347,7 +347,7 @@ public class SaSsoHandle {
* @return loginId
*/
public static Object checkTicket(String ticket, String currUri) {
- SaSsoConfig cfg = SaManager.getConfig().getSso();
+ SaSsoConfig cfg = SaSsoManager.getConfig();
// --------- 两种模式
if(cfg.getIsHttp()) {
// 模式三:使用http请求校验ticket
diff --git a/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/SaSsoManager.java b/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/SaSsoManager.java
new file mode 100644
index 00000000..55999d1b
--- /dev/null
+++ b/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/SaSsoManager.java
@@ -0,0 +1,31 @@
+package cn.dev33.satoken.sso;
+
+import cn.dev33.satoken.config.SaSsoConfig;
+
+/**
+ * Sa-Token-SSO 模块 总控类
+ *
+ * @author kong
+ *
+ */
+public class SaSsoManager {
+
+ /**
+ * Sso 配置 Bean
+ */
+ private static SaSsoConfig config;
+ public static SaSsoConfig getConfig() {
+ if (config == null) {
+ synchronized (SaSsoManager.class) {
+ if (config == null) {
+ setConfig(new SaSsoConfig());
+ }
+ }
+ }
+ return config;
+ }
+ public static void setConfig(SaSsoConfig config) {
+ SaSsoManager.config = config;
+ }
+
+}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoTemplate.java b/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/SaSsoTemplate.java
similarity index 91%
rename from sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoTemplate.java
rename to sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/SaSsoTemplate.java
index 970fabae..8009faf5 100644
--- a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoTemplate.java
+++ b/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/SaSsoTemplate.java
@@ -7,9 +7,10 @@ import java.util.Set;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.config.SaSsoConfig;
-import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.sso.SaSsoConsts.ParamName;
+import cn.dev33.satoken.sso.exception.SaSsoException;
+import cn.dev33.satoken.sso.exception.SaSsoExceptionCode;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaFoxUtil;
@@ -54,7 +55,7 @@ public class SaSsoTemplate {
* @param loginId 账号id
*/
public void saveTicket(String ticket, Object loginId) {
- long ticketTimeout = SaManager.getConfig().getSso().getTicketTimeout();
+ long ticketTimeout = SaSsoManager.getConfig().getTicketTimeout();
SaManager.getSaTokenDao().set(splicingTicketSaveKey(ticket), String.valueOf(loginId), ticketTimeout);
}
@@ -64,7 +65,7 @@ public class SaSsoTemplate {
* @param loginId 账号id
*/
public void saveTicketIndex(String ticket, Object loginId) {
- long ticketTimeout = SaManager.getConfig().getSso().getTicketTimeout();
+ long ticketTimeout = SaSsoManager.getConfig().getTicketTimeout();
SaManager.getSaTokenDao().set(splicingTicketIndexKey(loginId), String.valueOf(ticket), ticketTimeout);
}
@@ -160,7 +161,7 @@ public class SaSsoTemplate {
public String buildServerAuthUrl(String clientLoginUrl, String back) {
// 服务端认证地址
- String serverUrl = SaManager.getConfig().getSso().getAuthUrl();
+ String serverUrl = SaSsoManager.getConfig().getAuthUrl();
// 对back地址编码
back = (back == null ? "" : back);
@@ -210,7 +211,7 @@ public class SaSsoTemplate {
// 1、是否是一个有效的url
if(SaFoxUtil.isUrl(url) == false) {
- throw new SaTokenException("无效redirect:" + url);
+ throw new SaSsoException("无效redirect:" + url).setCode(SaSsoExceptionCode.CODE_20001);
}
// 2、截取掉?后面的部分
@@ -222,7 +223,7 @@ public class SaSsoTemplate {
// 3、是否在[允许地址列表]之中
List authUrlList = Arrays.asList(getAllowUrl().replaceAll(" ", "").split(","));
if(SaStrategy.me.hasElement.apply(authUrlList, url) == false) {
- throw new SaTokenException("非法redirect:" + url);
+ throw new SaSsoException("非法redirect:" + url).setCode(SaSsoExceptionCode.CODE_20002);
}
// 校验通过 √
@@ -235,7 +236,7 @@ public class SaSsoTemplate {
*/
public String getAllowUrl() {
// 默认从配置文件中返回
- return SaManager.getConfig().getSso().getAllowUrl();
+ return SaSsoManager.getConfig().getAllowUrl();
}
/**
@@ -271,9 +272,9 @@ public class SaSsoTemplate {
*/
public String buildUserinfoUrl(Object loginId) {
// 拼接
- String userinfoUrl = SaManager.getConfig().getSso().getUserinfoUrl();
+ String userinfoUrl = SaSsoManager.getConfig().getUserinfoUrl();
userinfoUrl = SaFoxUtil.joinParam(userinfoUrl, ParamName.loginId, loginId);
- userinfoUrl = SaFoxUtil.joinParam(userinfoUrl, ParamName.secretkey, SaManager.getConfig().getSso().getSecretkey());
+ userinfoUrl = SaFoxUtil.joinParam(userinfoUrl, ParamName.secretkey, SaSsoManager.getConfig().getSecretkey());
// 返回
return userinfoUrl;
}
@@ -286,8 +287,8 @@ public class SaSsoTemplate {
* @param secretkey 秘钥
*/
public void checkSecretkey(String secretkey) {
- if(secretkey == null || secretkey.isEmpty() || secretkey.equals(SaManager.getConfig().getSso().getSecretkey()) == false) {
- throw new SaTokenException("无效秘钥:" + secretkey);
+ if(secretkey == null || secretkey.isEmpty() || secretkey.equals(SaSsoManager.getConfig().getSecretkey()) == false) {
+ throw new SaSsoException("无效秘钥:" + secretkey).setCode(SaSsoExceptionCode.CODE_20003);
}
}
@@ -300,7 +301,7 @@ public class SaSsoTemplate {
*/
public String buildCheckTicketUrl(String ticket, String ssoLogoutCallUrl) {
// 裸地址
- String url = SaManager.getConfig().getSso().getCheckTicketUrl();
+ String url = SaSsoManager.getConfig().getCheckTicketUrl();
// 拼接ticket参数
url = SaFoxUtil.joinParam(url, ParamName.ticket, ticket);
@@ -340,7 +341,7 @@ public class SaSsoTemplate {
return;
}
- String secretkey = SaManager.getConfig().getSso().getSecretkey();
+ String secretkey = SaSsoManager.getConfig().getSecretkey();
Set urlSet = session.get(SaSsoConsts.SLO_CALLBACK_SET_KEY, () -> new HashSet());
for (String url : urlSet) {
// 拼接:login参数、秘钥参数
@@ -357,7 +358,7 @@ public class SaSsoTemplate {
* @return 单点注销URL
*/
public String buildSloUrl(Object loginId) {
- SaSsoConfig ssoConfig = SaManager.getConfig().getSso();
+ SaSsoConfig ssoConfig = SaSsoManager.getConfig();
String url = ssoConfig.getSloUrl();
url = SaFoxUtil.joinParam(url, ParamName.loginId, loginId);
url = SaFoxUtil.joinParam(url, ParamName.secretkey, ssoConfig.getSecretkey());
@@ -389,7 +390,7 @@ public class SaSsoTemplate {
*/
public Object getUserinfo(Object loginId) {
String url = buildUserinfoUrl(loginId);
- return SaManager.getConfig().getSso().getSendHttp().apply(url);
+ return SaSsoManager.getConfig().getSendHttp().apply(url);
}
diff --git a/sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoUtil.java b/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/SaSsoUtil.java
similarity index 100%
rename from sa-token-core/src/main/java/cn/dev33/satoken/sso/SaSsoUtil.java
rename to sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/SaSsoUtil.java
diff --git a/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/exception/SaSsoException.java b/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/exception/SaSsoException.java
new file mode 100644
index 00000000..bfb926fe
--- /dev/null
+++ b/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/exception/SaSsoException.java
@@ -0,0 +1,56 @@
+package cn.dev33.satoken.sso.exception;
+
+import cn.dev33.satoken.exception.SaTokenException;
+
+
+/**
+ * 一个异常:代表 SSO 认证流程错误
+ *
+ * @author kong
+ */
+public class SaSsoException extends SaTokenException {
+
+ /**
+ * 序列化版本号
+ */
+ private static final long serialVersionUID = 6806129545290130114L;
+
+ /**
+ * 一个异常:代表 SSO 认证流程错误
+ * @param message 异常描述
+ */
+ public SaSsoException(String message) {
+ super(message);
+ }
+
+ /**
+ * 一个异常:代表 SSO 认证流程错误
+ * @param code 异常细分状态码
+ * @param message 异常描述
+ */
+ public SaSsoException(int code, String message) {
+ super(code, message);
+ }
+
+ /**
+ * 写入异常细分状态码
+ * @param code 异常细分状态码
+ * @return 对象自身
+ */
+ public SaSsoException setCode(int code) {
+ super.setCode(code);
+ return this;
+ }
+
+ /**
+ * 如果flag==true,则抛出message异常
+ * @param flag 标记
+ * @param message 异常信息
+ */
+ public static void throwBy(boolean flag, String message) {
+ if(flag) {
+ throw new SaSsoException(message);
+ }
+ }
+
+}
diff --git a/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/exception/SaSsoExceptionCode.java b/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/exception/SaSsoExceptionCode.java
new file mode 100644
index 00000000..2e47de04
--- /dev/null
+++ b/sa-token-plugin/sa-token-sso/src/main/java/cn/dev33/satoken/sso/exception/SaSsoExceptionCode.java
@@ -0,0 +1,25 @@
+package cn.dev33.satoken.sso.exception;
+
+/**
+ * 定义所有 SSO 异常细分状态码
+ *
+ * @author kong
+ * @date: 2022-4-25
+ */
+public class SaSsoExceptionCode {
+
+ /** redirect 重定向 url 是一个无效地址 */
+ public static final int CODE_20001 = 20001;
+
+ /** redirect 重定向 url 不在 allowUrl 允许的范围内 */
+ public static final int CODE_20002 = 20002;
+
+ /** 接口调用方提供的 secretkey 秘钥无效 */
+ public static final int CODE_20003 = 20003;
+
+ /** 提供的 ticket 是无效的 */
+ public static final int CODE_20004 = 20004;
+
+
+
+}
diff --git a/sa-token-starter/sa-token-reactor-spring-boot-starter/pom.xml b/sa-token-starter/sa-token-reactor-spring-boot-starter/pom.xml
index 1cbbf220..15dac83c 100644
--- a/sa-token-starter/sa-token-reactor-spring-boot-starter/pom.xml
+++ b/sa-token-starter/sa-token-reactor-spring-boot-starter/pom.xml
@@ -51,6 +51,13 @@
${revision}
true
+
+
+ cn.dev33
+ sa-token-sso
+ ${revision}
+ true
+
diff --git a/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/SaBeanInject.java b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/SaBeanInject.java
index e2332ea3..4f1cb643 100644
--- a/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/SaBeanInject.java
+++ b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/SaBeanInject.java
@@ -14,8 +14,6 @@ import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.id.SaIdTemplate;
import cn.dev33.satoken.id.SaIdUtil;
import cn.dev33.satoken.listener.SaTokenListener;
-import cn.dev33.satoken.sso.SaSsoTemplate;
-import cn.dev33.satoken.sso.SaSsoUtil;
import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
@@ -119,16 +117,6 @@ public class SaBeanInject {
SaBasicUtil.saBasicTemplate = saBasicTemplate;
}
- /**
- * 注入 Sa-Token-SSO 单点登录模块 Bean
- *
- * @param saSsoTemplate saSsoTemplate对象
- */
- @Autowired(required = false)
- public void setSaSsoTemplate(SaSsoTemplate saSsoTemplate) {
- SaSsoUtil.saSsoTemplate = saSsoTemplate;
- }
-
/**
* 注入自定义的 StpLogic
* @param stpLogic /
diff --git a/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/sso/SaSsoBeanInject.java b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/sso/SaSsoBeanInject.java
new file mode 100644
index 00000000..7f2c4785
--- /dev/null
+++ b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/sso/SaSsoBeanInject.java
@@ -0,0 +1,40 @@
+package cn.dev33.satoken.reactor.spring.sso;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+
+import cn.dev33.satoken.config.SaSsoConfig;
+import cn.dev33.satoken.sso.SaSsoManager;
+import cn.dev33.satoken.sso.SaSsoTemplate;
+import cn.dev33.satoken.sso.SaSsoUtil;
+
+/**
+ * 注入 Sa-Token-SSO 所需要的Bean
+ *
+ * @author kong
+ *
+ */
+@ConditionalOnClass(SaSsoManager.class)
+public class SaSsoBeanInject {
+
+ /**
+ * 注入 Sa-Token-SSO 配置Bean
+ *
+ * @param saSsoConfig 配置对象
+ */
+ @Autowired(required = false)
+ public void setSaOAuth2Config(SaSsoConfig saSsoConfig) {
+ SaSsoManager.setConfig(saSsoConfig);
+ }
+
+ /**
+ * 注入 Sa-Token-SSO 单点登录模块 Bean
+ *
+ * @param saSsoTemplate saSsoTemplate对象
+ */
+ @Autowired(required = false)
+ public void setSaSsoTemplate(SaSsoTemplate saSsoTemplate) {
+ SaSsoUtil.saSsoTemplate = saSsoTemplate;
+ }
+
+}
diff --git a/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/sso/SaSsoBeanRegister.java b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/sso/SaSsoBeanRegister.java
new file mode 100644
index 00000000..86235f55
--- /dev/null
+++ b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/sso/SaSsoBeanRegister.java
@@ -0,0 +1,28 @@
+package cn.dev33.satoken.reactor.spring.sso;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+
+import cn.dev33.satoken.config.SaSsoConfig;
+import cn.dev33.satoken.sso.SaSsoManager;
+
+/**
+ * 注册 Sa-Token-SSO 所需要的Bean
+ * @author kong
+ *
+ */
+@ConditionalOnClass(SaSsoManager.class)
+public class SaSsoBeanRegister {
+
+ /**
+ * 获取 SSO 配置Bean
+ * @return 配置对象
+ */
+ @Bean
+ @ConfigurationProperties(prefix = "sa-token.sso")
+ public SaSsoConfig getSaSsoConfig() {
+ return new SaSsoConfig();
+ }
+
+}
diff --git a/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/sso/package-info.java b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/sso/package-info.java
new file mode 100644
index 00000000..f09169d9
--- /dev/null
+++ b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/java/cn/dev33/satoken/reactor/spring/sso/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Sa-Token-SSO 模块自动化配置(只有引入了 sa-token-sso 模块后,此包下的代码才会开始工作)
+ */
+package cn.dev33.satoken.reactor.spring.sso;
\ No newline at end of file
diff --git a/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/resources/META-INF/spring.factories b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/resources/META-INF/spring.factories
index 5946a982..7b239bbe 100644
--- a/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/resources/META-INF/spring.factories
+++ b/sa-token-starter/sa-token-reactor-spring-boot-starter/src/main/resources/META-INF/spring.factories
@@ -1,5 +1,7 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.dev33.satoken.reactor.spring.SaBeanRegister,\
cn.dev33.satoken.reactor.spring.SaBeanInject,\
+cn.dev33.satoken.reactor.spring.sso.SaSsoBeanRegister,\
+cn.dev33.satoken.reactor.spring.sso.SaSsoBeanInject,\
cn.dev33.satoken.reactor.spring.oauth2.SaOAuth2BeanRegister,\
cn.dev33.satoken.reactor.spring.oauth2.SaOAuth2BeanInject
\ No newline at end of file
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 4ae866fe..12f6e765 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
@@ -21,8 +21,6 @@ import cn.dev33.satoken.id.SaIdUtil;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.solon.integration.SaContextForSolon;
import cn.dev33.satoken.solon.integration.SaTokenMethodInterceptor;
-import cn.dev33.satoken.sso.SaSsoTemplate;
-import cn.dev33.satoken.sso.SaSsoUtil;
import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
@@ -92,11 +90,6 @@ public class XPluginImp implements Plugin {
SaBasicUtil.saBasicTemplate = bw.raw();
});
- // Sa-Token-SSO 单点登录模块 Bean
- Aop.getAsyn(SaSsoTemplate.class, bw->{
- SaSsoUtil.saSsoTemplate = bw.raw();
- });
-
// 自定义 StpLogic 对象
Aop.getAsyn(StpLogic.class, bw->{
StpUtil.setStpLogic(bw.raw());
diff --git a/sa-token-starter/sa-token-spring-boot-starter/pom.xml b/sa-token-starter/sa-token-spring-boot-starter/pom.xml
index b21c5483..07e87810 100644
--- a/sa-token-starter/sa-token-spring-boot-starter/pom.xml
+++ b/sa-token-starter/sa-token-spring-boot-starter/pom.xml
@@ -34,6 +34,14 @@
${revision}
true
+
+
+ cn.dev33
+ sa-token-sso
+ ${revision}
+ true
+
+
org.springframework.boot
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/SaSsoBeanInject.java b/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/SaSsoBeanInject.java
new file mode 100644
index 00000000..3adbb3d5
--- /dev/null
+++ b/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/SaSsoBeanInject.java
@@ -0,0 +1,40 @@
+package cn.dev33.satoken.spring.sso;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+
+import cn.dev33.satoken.config.SaSsoConfig;
+import cn.dev33.satoken.sso.SaSsoManager;
+import cn.dev33.satoken.sso.SaSsoTemplate;
+import cn.dev33.satoken.sso.SaSsoUtil;
+
+/**
+ * 注入 Sa-Token-SSO 所需要的Bean
+ *
+ * @author kong
+ *
+ */
+@ConditionalOnClass(SaSsoManager.class)
+public class SaSsoBeanInject {
+
+ /**
+ * 注入 Sa-Token-SSO 配置Bean
+ *
+ * @param saSsoConfig 配置对象
+ */
+ @Autowired(required = false)
+ public void setSaOAuth2Config(SaSsoConfig saSsoConfig) {
+ SaSsoManager.setConfig(saSsoConfig);
+ }
+
+ /**
+ * 注入 Sa-Token-SSO 单点登录模块 Bean
+ *
+ * @param saSsoTemplate saSsoTemplate对象
+ */
+ @Autowired(required = false)
+ public void setSaSsoTemplate(SaSsoTemplate saSsoTemplate) {
+ SaSsoUtil.saSsoTemplate = saSsoTemplate;
+ }
+
+}
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/SaSsoBeanRegister.java b/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/SaSsoBeanRegister.java
new file mode 100644
index 00000000..ce38e199
--- /dev/null
+++ b/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/SaSsoBeanRegister.java
@@ -0,0 +1,28 @@
+package cn.dev33.satoken.spring.sso;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+
+import cn.dev33.satoken.config.SaSsoConfig;
+import cn.dev33.satoken.sso.SaSsoManager;
+
+/**
+ * 注册 Sa-Token-SSO 所需要的Bean
+ * @author kong
+ *
+ */
+@ConditionalOnClass(SaSsoManager.class)
+public class SaSsoBeanRegister {
+
+ /**
+ * 获取 SSO 配置Bean
+ * @return 配置对象
+ */
+ @Bean
+ @ConfigurationProperties(prefix = "sa-token.sso")
+ public SaSsoConfig getSaSsoConfig() {
+ return new SaSsoConfig();
+ }
+
+}
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/package-info.java b/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/package-info.java
new file mode 100644
index 00000000..feddd29a
--- /dev/null
+++ b/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Sa-Token-SSO 模块自动化配置(只有引入了 sa-token-sso 模块后,此包下的代码才会开始工作)
+ */
+package cn.dev33.satoken.spring.sso;
\ No newline at end of file
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/resources/META-INF/spring.factories b/sa-token-starter/sa-token-spring-boot-starter/src/main/resources/META-INF/spring.factories
index ec266d80..d092a911 100644
--- a/sa-token-starter/sa-token-spring-boot-starter/src/main/resources/META-INF/spring.factories
+++ b/sa-token-starter/sa-token-spring-boot-starter/src/main/resources/META-INF/spring.factories
@@ -1,5 +1,7 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.dev33.satoken.spring.SaBeanRegister,\
cn.dev33.satoken.spring.SaBeanInject,\
+cn.dev33.satoken.spring.sso.SaSsoBeanRegister,\
+cn.dev33.satoken.spring.sso.SaSsoBeanInject,\
cn.dev33.satoken.spring.oauth2.SaOAuth2BeanRegister,\
cn.dev33.satoken.spring.oauth2.SaOAuth2BeanInject
\ No newline at end of file