From ec473a00d41bb4045deeb896095f8ce8e36a82ea Mon Sep 17 00:00:00 2001 From: chenbowen Date: Wed, 5 Nov 2025 16:29:40 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E5=8D=87=E7=BA=A7=20skywalking=20?= =?UTF-8?q?=E5=AF=B9=E5=BA=94=E4=BE=9D=E8=B5=96=E7=89=88=E6=9C=AC=202.=20?= =?UTF-8?q?=E6=95=B4=E5=90=88=20eban=20=E7=9B=B8=E5=85=B3=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=EF=BC=8C=E6=96=B0=E5=A2=9E=E7=99=BB=E5=87=BA=E6=97=B6?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=85=A8=E5=B1=80=E5=A4=B1=E6=95=88=20eban?= =?UTF-8?q?=20token=20=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zt-dependencies/pom.xml | 2 +- .../admin/auth/vo/AuthLoginRespVO.java | 6 ++ .../service/auth/AdminAuthServiceImpl.java | 15 ++- .../service/oauth2/EbanOAuth2ServiceImpl.java | 10 +- .../service/oauth2/EbanTokenService.java | 11 ++ .../service/oauth2/EbanTokenServiceImpl.java | 102 ++++++++++++++++-- .../src/main/resources/application.yaml | 28 +++-- .../service/dept/DeptServiceImplTest.java | 6 +- zt-server/src/main/resources/application.yaml | 26 +++-- 9 files changed, 164 insertions(+), 42 deletions(-) diff --git a/zt-dependencies/pom.xml b/zt-dependencies/pom.xml index f283b9a4..b0e13122 100644 --- a/zt-dependencies/pom.xml +++ b/zt-dependencies/pom.xml @@ -56,7 +56,7 @@ 2.2.7 - 9.0.0 + 9.5.0 3.4.5 0.33.0 diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/auth/vo/AuthLoginRespVO.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/auth/vo/AuthLoginRespVO.java index 4adf4bca..27ff0ce2 100644 --- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/auth/vo/AuthLoginRespVO.java +++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/controller/admin/auth/vo/AuthLoginRespVO.java @@ -27,6 +27,12 @@ public class AuthLoginRespVO { @Schema(description = "刷新令牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "nice") private String refreshToken; + @Schema(description = "客户端编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "eban-oauth2-client") + private String clientId; + + @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1") + private Integer userType; + @Schema(description = "过期时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime expiresTime; diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/auth/AdminAuthServiceImpl.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/auth/AdminAuthServiceImpl.java index 6489d903..6b6246fb 100644 --- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/auth/AdminAuthServiceImpl.java +++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/auth/AdminAuthServiceImpl.java @@ -27,6 +27,7 @@ import com.zt.plat.module.system.enums.user.UserSourceEnum; import com.zt.plat.module.system.service.logger.LoginLogService; import com.zt.plat.module.system.service.member.MemberService; import com.zt.plat.module.system.service.oauth2.EbanOAuth2Service; +import com.zt.plat.module.system.service.oauth2.EbanTokenService; import com.zt.plat.module.system.service.oauth2.OAuth2TokenService; import com.zt.plat.module.system.service.social.SocialUserService; import com.zt.plat.module.system.service.user.AdminUserService; @@ -72,20 +73,22 @@ public class AdminAuthServiceImpl implements AdminAuthService { private SmsCodeApi smsCodeApi; @Resource private EbanOAuth2Service ebanOAuth2Service; + @Resource + private EbanTokenService ebanTokenService; @Value("${sync.encrypt-key}") private String encryptKey; // E办OAuth2配置 - @Value("${eban.oauth2.authorize-url:http://10.2.137.42/idp/oauth2/authorize}") + @Value("${eban.oauth2.authorize-url}") private String ebanAuthorizeUrl; - @Value("${eban.oauth2.client-id:tyszhjyglxt}") + @Value("${eban.oauth2.client-id}") private String ebanClientId; - @Value("${eban.oauth2.redirect-uri:http://172.16.46.63:30080/system/oauth2/callback}") + @Value("${eban.oauth2.redirect-uri}") private String ebanRedirectUri; - @Value("${eban.oauth2.response-type:code}") + @Value("${eban.oauth2.response-type}") private String ebanResponseType; /** @@ -308,6 +311,9 @@ public class AdminAuthServiceImpl implements AdminAuthService { if (accessTokenDO == null) { return; } + if (EbanTokenService.EBAN_CLIENT_ID.equals(accessTokenDO.getClientId())) { + ebanTokenService.globalLogout(accessTokenDO.getAccessToken(), accessTokenDO.getUserId()); + } // 删除成功,则记录登出日志 createLogoutLog(accessTokenDO.getUserId(), accessTokenDO.getUserType(), logType); } @@ -460,7 +466,6 @@ public class AdminAuthServiceImpl implements AdminAuthService { */ private String buildEbanLoginUrl() { String state = "login_" + System.currentTimeMillis(); - return String.format("%s?client_id=%s&redirect_uri=%s&response_type=%s&state=%s", ebanAuthorizeUrl, ebanClientId, ebanRedirectUri, ebanResponseType, state); } diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/oauth2/EbanOAuth2ServiceImpl.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/oauth2/EbanOAuth2ServiceImpl.java index 40cea9c9..0aa803e0 100644 --- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/oauth2/EbanOAuth2ServiceImpl.java +++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/oauth2/EbanOAuth2ServiceImpl.java @@ -47,19 +47,19 @@ public class EbanOAuth2ServiceImpl implements EbanOAuth2Service { @Resource private EbanTokenService ebanTokenService; - @Value("${eban.oauth2.auth-server.base-url:http://10.2.137.42/idp/oauth2}") + @Value("${eban.oauth2.auth-server.base-url}") private String authServerBaseUrl; - @Value("${eban.oauth2.auth-server.client-id:tyszhjyglxt}") + @Value("${eban.oauth2.auth-server.client-id}") private String clientId; - @Value("${eban.oauth2.auth-server.client-secret:}") + @Value("${eban.oauth2.auth-server.client-secret}") private String clientSecret; - @Value("${eban.oauth2.user-info.url:http://10.2.137.42/idp/oauth2/getUserInfo}") + @Value("${eban.oauth2.user-info.url}") private String userInfoUrl; - @Value("${eban.oauth2.token.url:http://10.2.137.42/idp/oauth2/getToken}") + @Value("${eban.oauth2.token.url}") private String tokenUrl; @Override diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/oauth2/EbanTokenService.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/oauth2/EbanTokenService.java index 85bab9f4..7c0d2bef 100644 --- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/oauth2/EbanTokenService.java +++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/oauth2/EbanTokenService.java @@ -9,6 +9,8 @@ import com.zt.plat.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; */ public interface EbanTokenService { + String EBAN_CLIENT_ID = "eban-oauth2-client"; + /** * 创建E办Token信息到现有OAuth2表中 * @@ -61,4 +63,13 @@ public interface EbanTokenService { * @return OAuth2AccessTokenDO */ OAuth2AccessTokenDO getEbanTokenByAccessToken(String accessToken); + + /** + * 调用E办全局登出接口 + * + * @param accessToken E办访问令牌 + * @param userId 系统用户ID + * @return 是否登出成功 + */ + boolean globalLogout(String accessToken, Long userId); } \ No newline at end of file diff --git a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/oauth2/EbanTokenServiceImpl.java b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/oauth2/EbanTokenServiceImpl.java index f2a907bc..5cad514f 100644 --- a/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/oauth2/EbanTokenServiceImpl.java +++ b/zt-module-system/zt-module-system-server/src/main/java/com/zt/plat/module/system/service/oauth2/EbanTokenServiceImpl.java @@ -1,7 +1,6 @@ package com.zt.plat.module.system.service.oauth2; import cn.hutool.core.date.LocalDateTimeUtil; -import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; @@ -36,19 +35,30 @@ public class EbanTokenServiceImpl implements EbanTokenService { @Resource private OAuth2AccessTokenMapper oauth2AccessTokenMapper; - @Value("${eban.oauth2.auth-server.client-id:tyszhjyglxt}") + @Value("${eban.oauth2.auth-server.client-id}") private String clientId; - @Value("${eban.oauth2.auth-server.client-secret:}") + @Value("${eban.oauth2.auth-server.client-secret}") private String clientSecret; - @Value("${eban.oauth2.token.refresh-url:http://10.2.137.42/idp/oauth2/refreshToken}") + @Value("${eban.oauth2.token.refresh-url}") private String refreshTokenUrl; - @Value("${eban.oauth2.token.check-url:http://10.2.137.42/idp/oauth2/checkTokenValid}") + @Value("${eban.oauth2.token.check-url}") private String checkTokenUrl; - private static final String EBAN_CLIENT_ID = "eban-oauth2-client"; + @Value("${eban.oauth2.logout.url}") + private String globalLogoutUrl; + + @Value("${eban.oauth2.logout.entity-id}") + private String globalLogoutEntityId; + + @Value("${eban.oauth2.logout.protocol}") + private String globalLogoutProtocol; + + @Value("${eban.oauth2.logout.token-type}") + private String globalLogoutTokenType; + private static final String GRANT_TYPE_REFRESH_TOKEN = "refresh_token"; @Override @@ -62,7 +72,7 @@ public class EbanTokenServiceImpl implements EbanTokenService { } LocalDateTime expiresTime = calculateExpiresTime(expiresIn); - Map userInfoMap = MapUtil.newHashMap(6, false); + Map userInfoMap = new HashMap<>(6); if (StrUtil.isNotBlank(userInfo.getLoginName())) { userInfoMap.put("username", userInfo.getLoginName()); } @@ -152,7 +162,17 @@ public class EbanTokenServiceImpl implements EbanTokenService { @Override public void deleteEbanToken(Long userId) { - if (oauth2AccessTokenMapper.deleteByUserIdAndClientId(userId, EBAN_CLIENT_ID) > 0) { + OAuth2AccessTokenDO tokenDO = getEbanTokenByUserId(userId); + if (tokenDO == null) { + return; + } + + globalLogout(tokenDO.getAccessToken(), userId); + + int rows = tokenDO.getId() != null + ? oauth2AccessTokenMapper.deleteById(tokenDO.getId()) + : oauth2AccessTokenMapper.deleteByUserIdAndClientId(userId, EBAN_CLIENT_ID); + if (rows > 0) { log.info("已删除用户{}的E办Token", userId); } } @@ -187,6 +207,72 @@ public class EbanTokenServiceImpl implements EbanTokenService { return StrUtil.equalsIgnoreCase(json.getStr("result"), "true"); } + @Override + public boolean globalLogout(String accessToken, Long userId) { + String entityId = StrUtil.blankToDefault(globalLogoutEntityId, clientId); + String protocol = StrUtil.blankToDefault(globalLogoutProtocol, "oauth"); + String tokenType = StrUtil.blankToDefault(globalLogoutTokenType, "token"); + + if (StrUtil.isBlank(entityId)) { + log.warn("调用E办全局登出时缺少entityId配置,userId={}", userId); + return false; + } + if (StrUtil.isBlank(accessToken) && !StrUtil.equalsIgnoreCase(tokenType, "fromWeb")) { + log.warn("调用E办全局登出时缺少accessToken,userId={},tokenType={}", userId, tokenType); + return false; + } + + Map params = new HashMap<>(4); + params.put("entityId", entityId); + params.put("protocol", protocol); + params.put("tokenType", tokenType); + if (StrUtil.isNotBlank(accessToken)) { + params.put("token", accessToken); + } + + HttpResponse response = HttpRequest.get(globalLogoutUrl) + .form(params) + .timeout(10000) + .execute(); + if (!response.isOk()) { + log.error("调用E办全局登出失败,userId={},状态码={},响应={}", userId, response.getStatus(), response.body()); + return false; + } + + JSONObject json = parseJson(response.body()); + if (json.isEmpty()) { + log.warn("调用E办全局登出返回空响应,userId={},body={}", userId, response.body()); + return false; + } + if (json.containsKey("errcode")) { + log.warn("调用E办全局登出返回错误,userId={},错误码={},信息={}", userId, json.getStr("errcode"), json.getStr("msg")); + return false; + } + + boolean success = false; + String result = json.getStr("result"); + if (StrUtil.isNotBlank(result)) { + success = StrUtil.equalsIgnoreCase(result, "true") + || StrUtil.equalsIgnoreCase(result, "success") + || StrUtil.equalsIgnoreCase(result, "ok"); + } + if (!success && json.containsKey("success")) { + success = Boolean.TRUE.equals(json.getBool("success")); + } + if (!success && json.containsKey("status")) { + success = StrUtil.equalsIgnoreCase(json.getStr("status"), "200") + || StrUtil.equalsIgnoreCase(json.getStr("status"), "success") + || StrUtil.equalsIgnoreCase(json.getStr("status"), "true"); + } + + if (success) { + log.info("调用E办全局登出成功,userId={}", userId); + } else { + log.warn("调用E办全局登出未返回明确成功标识,userId={},响应={}", userId, json); + } + return success; + } + private LocalDateTime calculateExpiresTime(Integer expiresIn) { int seconds = expiresIn != null && expiresIn > 0 ? expiresIn : 3600; return LocalDateTimeUtil.offset(LocalDateTime.now(), seconds, ChronoUnit.SECONDS); diff --git a/zt-module-system/zt-module-system-server/src/main/resources/application.yaml b/zt-module-system/zt-module-system-server/src/main/resources/application.yaml index ea2d092f..5f925b91 100644 --- a/zt-module-system/zt-module-system-server/src/main/resources/application.yaml +++ b/zt-module-system/zt-module-system-server/src/main/resources/application.yaml @@ -207,20 +207,26 @@ zt: # E办OAuth2配置文件 eban: oauth2: - # E办OAuth2服务端配置 + authorize-url: ${eban.oauth2.auth-server.base-url}/authorize + client-id: tyszhjyglxt + client-secret: fa821b567e59448e9acea3937529d1b4 # 需要从 e 办系统获取 + redirect-uri: http://172.16.46.63:30080/system/oauth2/callback + response-type: code auth-server: base-url: http://10.2.137.42/idp/oauth2 - client-id: tyszhjyglxt - client-secret: fa821b567e59448e9acea3937529d1b4 # 需要从e办系统获取 - callback-uri: http://172.16.46.63:30080/system/oauth2/callback - - # 用户信息获取配置 - user-info: - url: http://10.2.137.42/idp/oauth2/getUserInfo - - # 令牌交换配置 + client-id: ${eban.oauth2.client-id} + client-secret: ${eban.oauth2.client-secret} token: - url: http://10.2.137.42/idp/oauth2/getToken + url: ${eban.oauth2.auth-server.base-url}/getToken + refresh-url: ${eban.oauth2.auth-server.base-url}/refreshToken + check-url: ${eban.oauth2.auth-server.base-url}/checkTokenValid + logout: + url: http://10.2.137.42/idp/profile/AllChannel/Redirect/GLO + entity-id: tyszhjyglxt + protocol: oauth + token-type: token + user-info: + url: ${eban.oauth2.auth-server.base-url}/getUserInfo debug: false diff --git a/zt-module-system/zt-module-system-server/src/test/java/com/zt/plat/module/system/service/dept/DeptServiceImplTest.java b/zt-module-system/zt-module-system-server/src/test/java/com/zt/plat/module/system/service/dept/DeptServiceImplTest.java index 8ce4a892..6520d2fb 100644 --- a/zt-module-system/zt-module-system-server/src/test/java/com/zt/plat/module/system/service/dept/DeptServiceImplTest.java +++ b/zt-module-system/zt-module-system-server/src/test/java/com/zt/plat/module/system/service/dept/DeptServiceImplTest.java @@ -252,7 +252,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest { deptMapper.insert(parentDept); // mock 同级重名部门 - String duplicateName = randomString(6); + String duplicateName = randomString(); DeptDO deptDO = randomPojo(DeptDO.class, o -> { o.setParentId(parentDept.getId()); o.setName(duplicateName); @@ -268,7 +268,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest { @Test public void testValidateDeptNameUnique_topLevelDuplicateAllowed() { // mock 顶级部门 - String duplicateName = randomString(6); + String duplicateName = randomString(); DeptDO topLevelDept = randomPojo(DeptDO.class, o -> { o.setParentId(DeptDO.PARENT_ID_ROOT); o.setName(duplicateName); @@ -294,7 +294,7 @@ public class DeptServiceImplTest extends BaseDbUnitTest { }).setDeptSource(null); deptMapper.insert(parentB); - String duplicateName = randomString(6); + String duplicateName = randomString(); DeptDO childUnderA = randomPojo(DeptDO.class, o -> { o.setParentId(parentA.getId()); o.setName(duplicateName); diff --git a/zt-server/src/main/resources/application.yaml b/zt-server/src/main/resources/application.yaml index 650f7b49..d502e1d9 100644 --- a/zt-server/src/main/resources/application.yaml +++ b/zt-server/src/main/resources/application.yaml @@ -349,18 +349,26 @@ zt: # E办OAuth2配置文件 eban: oauth2: - # E办OAuth2登录配置 - authorize-url: http://10.2.137.42/idp/oauth2/authorize + authorize-url: ${eban.oauth2.auth-server.base-url}/authorize client-id: tyszhjyglxt - client-secret: fa821b567e59448e9acea3937529d1b4 # 需要从e办系统获取 + client-secret: fa821b567e59448e9acea3937529d1b4 # 需要从 e 办系统获取 redirect-uri: http://172.16.46.63:30080/system/oauth2/callback response-type: code - - # 用户信息获取URL - user-info-url: http://10.2.137.42/idp/oauth2/getUserInfo - - # 令牌交换URL - token-url: http://10.2.137.42/idp/oauth2/getToken + auth-server: + base-url: http://10.2.137.42/idp/oauth2 + client-id: ${eban.oauth2.client-id} + client-secret: ${eban.oauth2.client-secret} + token: + url: ${eban.oauth2.auth-server.base-url}/getToken + refresh-url: ${eban.oauth2.auth-server.base-url}/refreshToken + check-url: ${eban.oauth2.auth-server.base-url}/checkTokenValid + logout: + url: http://10.2.137.42/idp/profile/AllChannel/Redirect/GLO + entity-id: tyszhjyglxt + protocol: oauth + token-type: token + user-info: + url: ${eban.oauth2.auth-server.base-url}/getUserInfo debug: false