diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java index f669b30e0..dc1373d43 100644 --- a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java +++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java @@ -30,6 +30,7 @@ import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginResponse; import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser; import cn.stylefeng.roses.kernel.auth.api.pojo.payload.DefaultJwtPayload; import cn.stylefeng.roses.kernel.auth.api.pojo.sso.LoginBySsoTokenRequest; +import cn.stylefeng.roses.kernel.auth.api.pojo.sso.LogoutBySsoTokenRequest; /** * 认证服务的接口,包括基本的登录退出操作和校验token等操作 @@ -136,4 +137,14 @@ public interface AuthServiceApi { */ LoginUser createNewLoginInfo(String token, DefaultJwtPayload defaultJwtPayload); + /** + * 通过单点的CaToken将本系统的用户退出 + *
+ * 一般用在单点认证中心退出时,认证中心调用本系统退出接口
+ *
+ * @author fengshuonan
+ * @since 2023/11/7 15:57
+ */
+ void logoutByCaToken(LogoutBySsoTokenRequest logoutBySsoTokenRequest);
+
}
diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/pojo/sso/LogoutBySsoTokenRequest.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/pojo/sso/LogoutBySsoTokenRequest.java
new file mode 100644
index 000000000..273e79c71
--- /dev/null
+++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/pojo/sso/LogoutBySsoTokenRequest.java
@@ -0,0 +1,25 @@
+package cn.stylefeng.roses.kernel.auth.api.pojo.sso;
+
+import cn.stylefeng.roses.kernel.rule.pojo.request.BaseRequest;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * 通过单点的token退出系统
+ *
+ * @author fengshuonan
+ * @since 2023/11/7 16:09
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class LogoutBySsoTokenRequest extends BaseRequest {
+
+ /**
+ * 从单点服务获取到的token
+ */
+ @NotBlank(message = "CA Token不能为空")
+ private String caToken;
+
+}
diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java
index 845b159be..62902e483 100644
--- a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java
+++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java
@@ -47,6 +47,7 @@ import cn.stylefeng.roses.kernel.auth.api.pojo.payload.DefaultJwtPayload;
import cn.stylefeng.roses.kernel.auth.api.pojo.sso.DecryptCaLoginUser;
import cn.stylefeng.roses.kernel.auth.api.pojo.sso.DecryptCaTokenInfo;
import cn.stylefeng.roses.kernel.auth.api.pojo.sso.LoginBySsoTokenRequest;
+import cn.stylefeng.roses.kernel.auth.api.pojo.sso.LogoutBySsoTokenRequest;
import cn.stylefeng.roses.kernel.cache.api.CacheOperatorApi;
import cn.stylefeng.roses.kernel.demo.expander.DemoConfigExpander;
import cn.stylefeng.roses.kernel.jwt.api.JwtApi;
@@ -121,7 +122,12 @@ public class AuthServiceImpl implements AuthServiceApi {
// aes解密出用户信息
AES aesUtil = SecureUtil.aes(Base64.decode(AuthConfigExpander.getSsoDataDecryptSecret()));
- String userInfoJson = aesUtil.decryptStr(encryptUserInfo, CharsetUtil.CHARSET_UTF_8);
+ String userInfoJson = null;
+ try {
+ userInfoJson = aesUtil.decryptStr(encryptUserInfo, CharsetUtil.CHARSET_UTF_8);
+ } catch (Exception e) {
+ throw new AuthException(AuthExceptionEnum.SSO_TOKEN_PARSE_ERROR, "sso token无法解析");
+ }
// 转化为实体类
DecryptCaTokenInfo decryptCaTokenInfo = JSON.parseObject(userInfoJson, DecryptCaTokenInfo.class);
@@ -246,4 +252,19 @@ public class AuthServiceImpl implements AuthServiceApi {
return loginUser;
}
+ @Override
+ public void logoutByCaToken(LogoutBySsoTokenRequest logoutBySsoTokenRequest) {
+
+ // 通过CaToken查询到本地是否有对应的会话
+ String localGunsToken = caClientTokenCacheApi.get(logoutBySsoTokenRequest.getCaToken());
+
+ // 如果缓存不存在则直接返回
+ if (ObjectUtil.isEmpty(localGunsToken)) {
+ return;
+ }
+
+ // 如果缓存存在,则直接移除token
+ this.sessionManagerApi.removeSession(localGunsToken);
+ }
+
}
diff --git a/kernel-d-config/config-business/src/main/java/cn/stylefeng/roses/kernel/config/modular/strategy/DefaultStrategyImpl.java b/kernel-d-config/config-business/src/main/java/cn/stylefeng/roses/kernel/config/modular/strategy/DefaultStrategyImpl.java
index e49560f7d..2481546cb 100644
--- a/kernel-d-config/config-business/src/main/java/cn/stylefeng/roses/kernel/config/modular/strategy/DefaultStrategyImpl.java
+++ b/kernel-d-config/config-business/src/main/java/cn/stylefeng/roses/kernel/config/modular/strategy/DefaultStrategyImpl.java
@@ -44,6 +44,7 @@ public class DefaultStrategyImpl implements ConfigInitStrategyApi {
configInitItems.add(new ConfigInitItem("系统默认密码", "SYS_DEFAULT_PASSWORD", "123456", "用在重置密码的默认密码"));
configInitItems.add(new ConfigInitItem("系统发布版本", "SYS_RELEASE_VERSION", DateUtil.format(new Date(), "yyyyMMdd"), "系统发布的版本号"));
configInitItems.add(new ConfigInitItem("数据库加密AES秘钥", "SYS_ENCRYPT_SECRET_KEY", RandomUtil.randomString(32), "对称加密秘钥,用在数据库数据加密"));
+ configInitItems.add(new ConfigInitItem("SSO服务端加密Token信息秘钥", "SYS_AUTH_SSO_DECRYPT_DATA_SECRET", RandomUtil.randomString(32), "SSO服务端加密Token信息秘钥,用在单点登录认证时候加密生成Token"));
return configInitItems;
}
diff --git a/kernel-s-system/system-business-permission/src/main/java/cn/stylefeng/roses/kernel/sys/modular/login/controller/SsoLoginController.java b/kernel-s-system/system-business-permission/src/main/java/cn/stylefeng/roses/kernel/sys/modular/login/controller/SsoLoginController.java
index ea9c434bb..d8159361a 100644
--- a/kernel-s-system/system-business-permission/src/main/java/cn/stylefeng/roses/kernel/sys/modular/login/controller/SsoLoginController.java
+++ b/kernel-s-system/system-business-permission/src/main/java/cn/stylefeng/roses/kernel/sys/modular/login/controller/SsoLoginController.java
@@ -3,9 +3,11 @@ package cn.stylefeng.roses.kernel.sys.modular.login.controller;
import cn.stylefeng.roses.kernel.auth.api.AuthServiceApi;
import cn.stylefeng.roses.kernel.auth.api.pojo.auth.LoginResponse;
import cn.stylefeng.roses.kernel.auth.api.pojo.sso.LoginBySsoTokenRequest;
+import cn.stylefeng.roses.kernel.auth.api.pojo.sso.LogoutBySsoTokenRequest;
import cn.stylefeng.roses.kernel.rule.pojo.response.ResponseData;
import cn.stylefeng.roses.kernel.rule.pojo.response.SuccessResponseData;
import cn.stylefeng.roses.kernel.scanner.api.annotation.ApiResource;
+import cn.stylefeng.roses.kernel.scanner.api.annotation.GetResource;
import cn.stylefeng.roses.kernel.scanner.api.annotation.PostResource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
@@ -29,15 +31,27 @@ public class SsoLoginController {
private AuthServiceApi authServiceApi;
/**
- * 通过单带登录
+ * 通过单点服务的CaToken进行登录
*
* @author fengshuonan
* @since 2023/11/7 14:12
*/
- @PostResource(name = "系统登录接口", path = "/loginByCaToken", requiredLogin = false)
- public ResponseData