From b1ccfb1b666686ff2ac3a65bbf1234bab7e01bb5 Mon Sep 17 00:00:00 2001 From: Mzaxd Date: Wed, 17 May 2023 15:45:10 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=E5=8D=95=E7=82=B9=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../da/login/rest/LoginRestController.java | 15 ++++ .../com/adc/da/sys/constant/SsoConstants.java | 55 ++++++++++++++ .../adc/da/sys/service/UserEOServiceImpl.java | 75 +++++++++++++++++++ .../sys/service/iservice/IUserEoService.java | 8 ++ .../com/adc/da/sys/vo/iam/SsoResponse.java | 26 +++++++ .../com/adc/da/sys/vo/iam/SsoUserInfo.java | 25 +++++++ .../da/sys/vo/iam/SsoUserInfoResponse.java | 23 ++++++ .../com/adc/da/sys/vo/iam/UserDetailInfo.java | 22 ++++++ 8 files changed, 249 insertions(+) create mode 100644 adc-da-sys/src/main/java/com/adc/da/sys/constant/SsoConstants.java create mode 100644 adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/SsoResponse.java create mode 100644 adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/SsoUserInfo.java create mode 100644 adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/SsoUserInfoResponse.java create mode 100644 adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/UserDetailInfo.java diff --git a/adc-da-login/src/main/java/com/adc/da/login/rest/LoginRestController.java b/adc-da-login/src/main/java/com/adc/da/login/rest/LoginRestController.java index 0edb2ef..1ebdb06 100644 --- a/adc-da-login/src/main/java/com/adc/da/login/rest/LoginRestController.java +++ b/adc-da-login/src/main/java/com/adc/da/login/rest/LoginRestController.java @@ -1,5 +1,6 @@ package com.adc.da.login.rest; +import cn.hutool.core.util.StrUtil; import com.adc.da.log.annotation.BusinessLog; import com.adc.da.login.entity.OnlineUserEO; import com.adc.da.login.security.SystemAuthorizingRealm; @@ -507,6 +508,20 @@ public class LoginRestController { return Result.success(); } + @GetMapping("/ssoLogin") + @ResponseBody + @ApiOperation(value = "SSO,根据Code返回用户信息") + public ResponseMessage ssoLogin(String code, HttpServletRequest request){ + if (StrUtil.isBlank(code)) { + return Result.error("无法单点登录,code为空"); + } + String username = userService.ssoLogin(code); + + UsernamePasswordToken token = new UsernamePasswordToken(username); + + return login(request, token); + } + public static void main(String[] args) throws Exception { String decrypt = EncryptUtil.decrypt("F6lnqMmPc/zkC8LcdSnDIMkH3Pt3DC1/53blM5P0FkM="); System.out.println(decrypt); diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/constant/SsoConstants.java b/adc-da-sys/src/main/java/com/adc/da/sys/constant/SsoConstants.java new file mode 100644 index 0000000..c9f3764 --- /dev/null +++ b/adc-da-sys/src/main/java/com/adc/da/sys/constant/SsoConstants.java @@ -0,0 +1,55 @@ +package com.adc.da.sys.constant; + +/** + * @author: CaiHaohan + * @Date: 2023/5/17 14:02 + * @Description: SSO单点登录所需常量 + */ +public class SsoConstants { + + /** + * 获取Token的路径 + */ + public static final String GET_TOKEN_PATH = "esc-sso/oauth2.0/accessToken?"; + + /** + * 获取Token的路径 + */ + public static final String GET_USERINFO_PATH = "esc-sso/oauth2.0/profile?"; + + /** + * 应用注册ID + */ + public static final String CLIENT_ID = "client_id="; + + /** + * 属性常量 + */ + public static final String GRANT_TYPE = "grant_type="; + + /** + * 属性常量 + */ + public static final String AUTHORIZATION_CODE = "authorization_code"; + + /** + * 接受到的code值 + */ + public static final String CODE = "code="; + + /** + * client_secret + */ + public static final String CLIENT_SECRET = "client_secret="; + + /** + * 应用回调地址,需要http格式化 + */ + public static final String REDIRECT_URI = "redirect_uri="; + + /** + * 获取的token的值 必须 + */ + public static final String ACCESS_TOKEN = "access_token="; + +} diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/service/UserEOServiceImpl.java b/adc-da-sys/src/main/java/com/adc/da/sys/service/UserEOServiceImpl.java index e616a1a..7c17193 100644 --- a/adc-da-sys/src/main/java/com/adc/da/sys/service/UserEOServiceImpl.java +++ b/adc-da-sys/src/main/java/com/adc/da/sys/service/UserEOServiceImpl.java @@ -1,5 +1,9 @@ package com.adc.da.sys.service; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.json.JSONUtil; +import com.adc.da.sys.constant.SsoConstants; import com.adc.da.sys.constant.SysConstants; import com.adc.da.sys.constant.UserBelongEnum; import com.adc.da.sys.dao.mysql.UserEODao; @@ -10,12 +14,15 @@ import com.adc.da.sys.service.iservice.IUserEoService; import com.adc.da.sys.util.EncryptUtil; import com.adc.da.sys.vo.UserImportVO; import com.adc.da.sys.vo.UserVO; +import com.adc.da.sys.vo.iam.SsoResponse; +import com.adc.da.sys.vo.iam.SsoUserInfoResponse; import com.adc.da.util.exception.AdcDaBaseException; import com.adc.da.util.utils.CollectionUtils; import com.adc.da.util.utils.StringUtils; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -36,6 +43,7 @@ import java.util.stream.Collectors; */ @Service("userEOService") @Transactional +@Slf4j public class UserEOServiceImpl implements IUserEoService { @@ -54,6 +62,15 @@ public class UserEOServiceImpl implements IUserEoService { @Resource private RoleEOService roleEOService; + @Value("${sso.clientId}") + private String ssoClientId; + + @Value("${sso.clientSecret}") + private String ssoClientSecret; + + @Value("${sso.url}") + private String ssoUrl; + /** * 获取角色信息,用户名,用于新增用户校验 @@ -342,6 +359,64 @@ public class UserEOServiceImpl implements IUserEoService { return dao.getOwnLeader(orgEOList); } + /** + * 获取【通过Code获取accessToken接口】的Url + * @param code code + * @return Url + */ + private String getTokenByCodeUrl(String code) { + return ssoUrl + SsoConstants.GET_TOKEN_PATH + + SsoConstants.GRANT_TYPE + SsoConstants.AUTHORIZATION_CODE + "&" + + SsoConstants.CLIENT_ID + ssoClientId + "&" + + SsoConstants.CLIENT_SECRET + ssoClientSecret + "&" + + SsoConstants.CODE + code + "&" + + SsoConstants.REDIRECT_URI + "XXX"; + } + + /** + * 获取【通过accessToken获取用户信息接口】的Url + * @param accessToken accessToken + * @return Url + */ + private String getUserInfoByTokenUrl(String accessToken) { + return ssoUrl + SsoConstants.GET_USERINFO_PATH + + SsoConstants.ACCESS_TOKEN + accessToken; + } + + @Override + public String ssoLogin(String code) { + //向SSO服务器发送code获取用户token + String getTokenByCodeUrl = getTokenByCodeUrl(code); + + String tokenResponse = HttpRequest.post(getTokenByCodeUrl).execute().body(); + + SsoResponse tokenResponseObject = JSONUtil.toBean(tokenResponse, SsoResponse.class); + //获取返回值中的token + String accessToken = tokenResponseObject.getAccess_token(); + + //向SSO服务器发送token获取用户数据 + if (StrUtil.isBlank(accessToken)) { + log.info("通过code获取accessToken失败"); + throw new AdcDaBaseException("通过code获取accessToken失败"); + } + + String getUserInfoByTokenUrl = getUserInfoByTokenUrl(accessToken); + String userInfoResponse = HttpRequest.get(getUserInfoByTokenUrl).execute().body(); + + SsoUserInfoResponse userInfoResponseObject = JSONUtil.toBean(userInfoResponse, SsoUserInfoResponse.class); + + //获取返回值中的用户id + String userId = userInfoResponseObject.getId(); + + //根据用户id取出用户名 + UserEO user = getUserById(userId); + if (user == null) { + log.info("根据用户id取出用户失败"); + throw new AdcDaBaseException("根据用户id取出用户失败"); + } + return user.getUsname(); + } + void checkExcel(List list) { if (CollectionUtils.isEmpty(list)) { throw new AdcDaBaseException("数据不能为空"); diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/service/iservice/IUserEoService.java b/adc-da-sys/src/main/java/com/adc/da/sys/service/iservice/IUserEoService.java index 35824d6..1732fed 100644 --- a/adc-da-sys/src/main/java/com/adc/da/sys/service/iservice/IUserEoService.java +++ b/adc-da-sys/src/main/java/com/adc/da/sys/service/iservice/IUserEoService.java @@ -70,4 +70,12 @@ public interface IUserEoService { UserVO getUserByIdNodel(String userId); List getOwnLeader(List orgEOList); + + /** + * IAM单点登录逻辑 + * + * @param code + * @return + */ + String ssoLogin(String code); } diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/SsoResponse.java b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/SsoResponse.java new file mode 100644 index 0000000..cd566b7 --- /dev/null +++ b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/SsoResponse.java @@ -0,0 +1,26 @@ +package com.adc.da.sys.vo.iam; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author: CaiHaohan + * @Date: 2023/5/17 14:22 + * @Description: + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SsoResponse { + + /** + * 返回的token 必须 + */ + private String access_token; + + /** + * 刷新token(在应用配置里,打开【token刷新】的开关,即可返回该参数) 非必须 + */ + private String refresh_token; +} diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/SsoUserInfo.java b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/SsoUserInfo.java new file mode 100644 index 0000000..ea75078 --- /dev/null +++ b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/SsoUserInfo.java @@ -0,0 +1,25 @@ +package com.adc.da.sys.vo.iam; + +import cn.hutool.system.UserInfo; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author: CaiHaohan + * @Date: 2023/5/17 15:04 + * @Description: + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SsoUserInfo { + + private String account_no; + + private String token_expired; + + private String token_gtime; + + private UserDetailInfo user_detail_info; +} diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/SsoUserInfoResponse.java b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/SsoUserInfoResponse.java new file mode 100644 index 0000000..698f7e2 --- /dev/null +++ b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/SsoUserInfoResponse.java @@ -0,0 +1,23 @@ +package com.adc.da.sys.vo.iam; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author: CaiHaohan + * @Date: 2023/5/17 15:08 + * @Description: + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SsoUserInfoResponse { + + /** + * 用户id + */ + private String id; + + private SsoUserInfo attributes; +} diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/UserDetailInfo.java b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/UserDetailInfo.java new file mode 100644 index 0000000..8921572 --- /dev/null +++ b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/UserDetailInfo.java @@ -0,0 +1,22 @@ +package com.adc.da.sys.vo.iam; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @author: CaiHaohan + * @Date: 2023/5/17 15:06 + * @Description: + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class UserDetailInfo { + + private List jobs; + private List userTypes; + private List orgs; +} From 71c23c2e1e29dbe62401d8e46109de7ee260462e Mon Sep 17 00:00:00 2001 From: Mzaxd Date: Wed, 17 May 2023 15:54:09 +0800 Subject: [PATCH 2/4] =?UTF-8?q?ci:=E5=B0=86sso=E8=8E=B7=E5=8F=96token?= =?UTF-8?q?=E5=92=8Csso=E8=8E=B7=E5=8F=96userInfo=E7=9A=84=E9=93=BE?= =?UTF-8?q?=E6=8E=A5=E8=B0=83=E6=95=B4=E4=B8=BA=E6=96=B0=E7=89=88=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/adc/da/sys/constant/SsoConstants.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/constant/SsoConstants.java b/adc-da-sys/src/main/java/com/adc/da/sys/constant/SsoConstants.java index c9f3764..8b5a5e9 100644 --- a/adc-da-sys/src/main/java/com/adc/da/sys/constant/SsoConstants.java +++ b/adc-da-sys/src/main/java/com/adc/da/sys/constant/SsoConstants.java @@ -10,12 +10,12 @@ public class SsoConstants { /** * 获取Token的路径 */ - public static final String GET_TOKEN_PATH = "esc-sso/oauth2.0/accessToken?"; + public static final String GET_TOKEN_PATH = "esc-sso/oauth2.0/accessToken/old?"; /** * 获取Token的路径 */ - public static final String GET_USERINFO_PATH = "esc-sso/oauth2.0/profile?"; + public static final String GET_USERINFO_PATH = "esc-sso/oauth2.0/profile/old?"; /** * 应用注册ID From 62c6cf3ef5a814811cc6728be34c2a110cbc6b70 Mon Sep 17 00:00:00 2001 From: Mzaxd Date: Wed, 17 May 2023 16:26:39 +0800 Subject: [PATCH 3/4] =?UTF-8?q?ci:=E8=B0=83=E6=95=B4=E5=9C=B0=E5=9D=80?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E6=97=A5=E5=BF=97=E6=89=93=E5=8D=B0?= =?UTF-8?q?=EF=BC=8C=E6=94=BE=E5=BC=80=E7=99=BB=E5=BD=95=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=8B=A6=E6=88=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adc/da/login/config/ShiroFilterConfiguration.java | 3 +++ .../com/adc/da/login/rest/LoginRestController.java | 10 +++++----- .../java/com/adc/da/sys/constant/SsoConstants.java | 4 ++-- .../java/com/adc/da/sys/service/UserEOServiceImpl.java | 9 +++++---- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/adc-da-login/src/main/java/com/adc/da/login/config/ShiroFilterConfiguration.java b/adc-da-login/src/main/java/com/adc/da/login/config/ShiroFilterConfiguration.java index 36140c7..8abfffe 100644 --- a/adc-da-login/src/main/java/com/adc/da/login/config/ShiroFilterConfiguration.java +++ b/adc-da-login/src/main/java/com/adc/da/login/config/ShiroFilterConfiguration.java @@ -87,6 +87,9 @@ public class ShiroFilterConfiguration { /* 校验单点登录ticket 不需要认证 */ filterChainDefinitionMap.put(restPath + "/login", ANON); + /* 校验单点登录ticket 不需要认证 */ + filterChainDefinitionMap.put(restPath + "/ssoLogin", ANON); + /* 登出不需认证 */ filterChainDefinitionMap.put(restPath + "/logout/**", ANON); diff --git a/adc-da-login/src/main/java/com/adc/da/login/rest/LoginRestController.java b/adc-da-login/src/main/java/com/adc/da/login/rest/LoginRestController.java index 1ebdb06..8cd8225 100644 --- a/adc-da-login/src/main/java/com/adc/da/login/rest/LoginRestController.java +++ b/adc-da-login/src/main/java/com/adc/da/login/rest/LoginRestController.java @@ -512,12 +512,12 @@ public class LoginRestController { @ResponseBody @ApiOperation(value = "SSO,根据Code返回用户信息") public ResponseMessage ssoLogin(String code, HttpServletRequest request){ - if (StrUtil.isBlank(code)) { - return Result.error("无法单点登录,code为空"); - } - String username = userService.ssoLogin(code); +// if (StrUtil.isBlank(code)) { +// return Result.error("无法单点登录,code为空"); +// } +// String username = userService.ssoLogin(code); - UsernamePasswordToken token = new UsernamePasswordToken(username); + UsernamePasswordToken token = new UsernamePasswordToken("chh"); return login(request, token); } diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/constant/SsoConstants.java b/adc-da-sys/src/main/java/com/adc/da/sys/constant/SsoConstants.java index 8b5a5e9..c9f3764 100644 --- a/adc-da-sys/src/main/java/com/adc/da/sys/constant/SsoConstants.java +++ b/adc-da-sys/src/main/java/com/adc/da/sys/constant/SsoConstants.java @@ -10,12 +10,12 @@ public class SsoConstants { /** * 获取Token的路径 */ - public static final String GET_TOKEN_PATH = "esc-sso/oauth2.0/accessToken/old?"; + public static final String GET_TOKEN_PATH = "esc-sso/oauth2.0/accessToken?"; /** * 获取Token的路径 */ - public static final String GET_USERINFO_PATH = "esc-sso/oauth2.0/profile/old?"; + public static final String GET_USERINFO_PATH = "esc-sso/oauth2.0/profile?"; /** * 应用注册ID diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/service/UserEOServiceImpl.java b/adc-da-sys/src/main/java/com/adc/da/sys/service/UserEOServiceImpl.java index 7c17193..e821bf8 100644 --- a/adc-da-sys/src/main/java/com/adc/da/sys/service/UserEOServiceImpl.java +++ b/adc-da-sys/src/main/java/com/adc/da/sys/service/UserEOServiceImpl.java @@ -385,29 +385,30 @@ public class UserEOServiceImpl implements IUserEoService { @Override public String ssoLogin(String code) { + log.info("SSO登录: Code为【{}】", code); //向SSO服务器发送code获取用户token - String getTokenByCodeUrl = getTokenByCodeUrl(code); + String getTokenByCodeUrl = this.getTokenByCodeUrl(code); String tokenResponse = HttpRequest.post(getTokenByCodeUrl).execute().body(); SsoResponse tokenResponseObject = JSONUtil.toBean(tokenResponse, SsoResponse.class); //获取返回值中的token String accessToken = tokenResponseObject.getAccess_token(); - + log.info("SSO登录: accessToken为【{}】", accessToken); //向SSO服务器发送token获取用户数据 if (StrUtil.isBlank(accessToken)) { log.info("通过code获取accessToken失败"); throw new AdcDaBaseException("通过code获取accessToken失败"); } - String getUserInfoByTokenUrl = getUserInfoByTokenUrl(accessToken); + String getUserInfoByTokenUrl = this.getUserInfoByTokenUrl(accessToken); String userInfoResponse = HttpRequest.get(getUserInfoByTokenUrl).execute().body(); SsoUserInfoResponse userInfoResponseObject = JSONUtil.toBean(userInfoResponse, SsoUserInfoResponse.class); //获取返回值中的用户id String userId = userInfoResponseObject.getId(); - + log.info("SSO登录: userId为【{}】", userId); //根据用户id取出用户名 UserEO user = getUserById(userId); if (user == null) { From 405d2d082835981eb9a8a0166e87b8282f34b499 Mon Sep 17 00:00:00 2001 From: "xuetao.li" Date: Wed, 17 May 2023 17:12:37 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E7=BC=96=E5=86=99=E5=AE=8C=E6=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/ShiroFilterConfiguration.java | 2 + .../main/resources/application-dev.properties | 11 +- .../src/main/resources/application.properties | 1 - .../com/adc/da/sync/service/SyncIAMTimer.java | 56 ++++--- .../service/controller/SyncController.java | 95 ++++++++++++ .../adc/da/sys/dao/mysql/UserOrgEODao.java | 2 + .../adc/da/sys/dao/mysql/UserRoleEODao.java | 2 + .../adc/da/sys/service/UserEOServiceImpl.java | 141 ++++++++++++++---- .../sys/service/iservice/IUserEoService.java | 2 +- .../adc/da/sys/vo/iam/CmpOrgInnerResult.java | 20 +++ .../com/adc/da/sys/vo/iam/CmpOrgResult.java | 2 +- .../adc/da/sys/vo/iam/CmpUserInnerResult.java | 20 +++ .../com/adc/da/sys/vo/iam/CmpUserResult.java | 2 +- .../mapper/sys/mysql/UserOrgEOMapper.xml | 8 + .../mapper/sys/mysql/UserRoleEOMapper.xml | 9 ++ 15 files changed, 305 insertions(+), 68 deletions(-) create mode 100644 adc-da-sys/src/main/java/com/adc/da/sync/service/controller/SyncController.java create mode 100644 adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpOrgInnerResult.java create mode 100644 adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpUserInnerResult.java diff --git a/adc-da-login/src/main/java/com/adc/da/login/config/ShiroFilterConfiguration.java b/adc-da-login/src/main/java/com/adc/da/login/config/ShiroFilterConfiguration.java index 36140c7..f60ca75 100644 --- a/adc-da-login/src/main/java/com/adc/da/login/config/ShiroFilterConfiguration.java +++ b/adc-da-login/src/main/java/com/adc/da/login/config/ShiroFilterConfiguration.java @@ -123,6 +123,8 @@ public class ShiroFilterConfiguration { /* 流程需要 */ filterChainDefinitionMap.put(restPath + "/service/model/**", ANON); filterChainDefinitionMap.put(restPath + "/service/editor/stencilset", ANON); + /* 同步需要 */ + filterChainDefinitionMap.put(restPath + "/sync/**", ANON); filterChainDefinitionMap.put(restPath + "/**", AUTHC); diff --git a/adc-da-main/src/main/resources/application-dev.properties b/adc-da-main/src/main/resources/application-dev.properties index 7f4f4b3..7a10004 100644 --- a/adc-da-main/src/main/resources/application-dev.properties +++ b/adc-da-main/src/main/resources/application-dev.properties @@ -132,17 +132,20 @@ huawei.OBS.fileMaxSize=10 #\u6587\u4EF6\u4E0A\u4F20\u6700\u5927M\u6570 logging.level.com.adc: debug -# CMP??????????? +# CMP TEST ENV cmp.url=https://cmp-uat.faw-vw.in/ cmp.appkey=TI062S001Uat cmp.appSecret=ee493505524d4f628e52058f4df3a4fb -# CMP??????????? +# CMP PROD ENV #cmp.url=https://cmp.faw-vw.in/employee/v1/ #cmp.appkey=TI062S001Uat #cmp.appSecret=ee493505524d4f628e52058f4df3a4fb -# SSO???? +# SSO TEST ENV sso.url=https://iamuat.faw-vw.com/ sso.clientId=43da19911e74a14dd5d9 -sso.clientSecret=67da1e83183e854535cae9027cfbdb12cbc3 \ No newline at end of file +sso.clientSecret=67da1e83183e854535cae9027cfbdb12cbc3 + +# ROLE FIX USER +user.fix.role=wei.sheng,miao.qi \ No newline at end of file diff --git a/adc-da-main/src/main/resources/application.properties b/adc-da-main/src/main/resources/application.properties index b958990..6bb9be5 100644 --- a/adc-da-main/src/main/resources/application.properties +++ b/adc-da-main/src/main/resources/application.properties @@ -72,7 +72,6 @@ queue.capacity=8 mybatis-plus.configuration.map-underscore-to-camel-case=true spring.activiti.database-schema-update=true -# ????????:true-???????false-?? spring.activiti.check-process-definitions=false diff --git a/adc-da-sys/src/main/java/com/adc/da/sync/service/SyncIAMTimer.java b/adc-da-sys/src/main/java/com/adc/da/sync/service/SyncIAMTimer.java index ec21646..f2810da 100644 --- a/adc-da-sys/src/main/java/com/adc/da/sync/service/SyncIAMTimer.java +++ b/adc-da-sys/src/main/java/com/adc/da/sync/service/SyncIAMTimer.java @@ -25,6 +25,7 @@ import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpMethod; +import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -40,15 +41,15 @@ public class SyncIAMTimer { * IAM的前缀地址 */ @Value("${cmp.url}") - private String cmpUrl="https://cmp-uat.faw-vw.in/"; + private String cmpUrl; @Value("${cmp.appkey}") - private String appkey = "TI062S001Uat"; + private String appkey; @Value("${cmp.appSecret}") - private String appSecret = "ee493505524d4f628e52058f4df3a4fb"; + private String appSecret; - private String xCustom = "TI062S-001"; // 写死的 + private final String xCustom = "TI062S-001"; // 写死的 /** * 组织机构增量同步接口地址 @@ -71,7 +72,8 @@ public class SyncIAMTimer { public static void main(String[] args) { SyncIAMTimer syncIAMTimer = new SyncIAMTimer(); - syncIAMTimer.syncOrgIncrData(1, 10); +// syncIAMTimer.syncOrgIncrData(1, 1000); + syncIAMTimer.syncUserIncrData(39, 1000, null); } /** @@ -80,7 +82,7 @@ public class SyncIAMTimer { * @Param pageIndex 页码,默认为1,小于1按1处理 * @Param pageSize 每页条数,默认10,小于1按1处 于1000按1000处理 */ - public void syncOrgIncrData(int pageIndex, int pageSize){ + public CmpOrgResult syncOrgIncrData(int pageIndex, int pageSize){ String suffixUrl = ORG_INCREMENT_URL + "?pageIndex=" + pageIndex + "&pageSize=" + pageSize; String syncUrl = this.cmpUrl + suffixUrl; @@ -101,7 +103,7 @@ public class SyncIAMTimer { CmpOrgResult cmpOrgResult = GsonUtil.json2T(orgDataStr, CmpOrgResult.class); if (cmpOrgResult != null){ - List orgVoIAMList = cmpOrgResult.getData(); + List orgVoIAMList = cmpOrgResult.getData().getRecords(); // 同步的VO 转换成 数据库EO List orgEOList = new ArrayList<>(); @@ -114,13 +116,15 @@ public class SyncIAMTimer { this.addSyncLog(null, new Date(), SyncTypeEnum.ORG_INCREMENT_DATA.getValue()); } + + return cmpOrgResult; } /** * 同步组织机构-增量数据并入库 * @Param syncModel 同步模式 */ - public void syncUserIncrData(int pageIndex, int pageSize, String enterTime){ + public CmpUserResult syncUserIncrData(int pageIndex, int pageSize, String enterTime){ String suffixUrl = USER_INCREMENT_URL + "?pageIndex=" + pageIndex + "&pageSize=" + pageSize; if (StringUtils.isNotEmpty(enterTime)){ suffixUrl += "&enterTime=" + enterTime; @@ -129,9 +133,9 @@ public class SyncIAMTimer { String syncUrl = this.cmpUrl + suffixUrl; String gmtDate = SignUtils.getGMTDate(); - String sign = SignUtils.generate(HttpMethod.GET, syncUrl, this.xCustom, this.appkey, gmtDate, this.appSecret); + String sign = SignUtils.generate(HttpMethod.GET, suffixUrl, this.xCustom, this.appkey, gmtDate, this.appSecret); - String userDataStr = HttpRequest.post(syncUrl) + String userDataStr = HttpRequest.get(syncUrl) .header("Content-Type", "application/json") .header("Date", gmtDate) .header("X-HMAC-ACCESS-KEY", this.appkey) @@ -144,32 +148,21 @@ public class SyncIAMTimer { CmpUserResult cmpUserResult = GsonUtil.json2T(userDataStr, CmpUserResult.class); if (cmpUserResult != null){ - List userVoIAMList =cmpUserResult.getData(); + List userVoIAMList =cmpUserResult.getData().getRecords(); + List waitSaveUserList = new ArrayList<>(); // 同步的VO 转换成 数据库EO,并存库 for (UserVoIAM userVoIAM : userVoIAMList){ UserEO userEO = this.transUserIAMVoToUserEO(userVoIAM); - this.iUserEoService.syncSaveOrUpdate(userEO); + waitSaveUserList.add(userEO); } + this.iUserEoService.syncSaveOrUpdate(waitSaveUserList); + this.addSyncLog(null, new Date(), SyncTypeEnum.USER_INCREMENT_DATA.getValue()); } - } - - /** - * 根据key和secret获取JWT_TOKEN - * @param appKey - * @param appSecret - * @return - */ - public String getJwtToken(String appKey, String appSecret) { - String token = JWT.create() - .withIssuer(appKey) - .withIssuedAt(new Date()) - .withJWTId(IdUtil.fastSimpleUUID()) - .sign(Algorithm.HMAC256(appSecret)); - return String.join(" ", "Bearer", token); + return cmpUserResult; } /** @@ -223,7 +216,7 @@ public class SyncIAMTimer { userEO.setAccount(userVoIAM.getAccount()); userEO.setCellPhoneNumber(userVoIAM.getMobile() == null ? EncryptUtil.encrypt("") : EncryptUtil.encrypt(userVoIAM.getMobile())); userEO.setCreateTime(userVoIAM.getEnterTime()); - userEO.setUpdateTime(userVoIAM.getEnterTime()); + userEO.setUpdateTime(DateUtil.formatDateTime(new Date())); userEO.setEmail(userVoIAM.getEmail() == null ? EncryptUtil.encrypt("") : EncryptUtil.encrypt(userVoIAM.getEmail())); userEO.setUsname(userVoIAM.getCnName()); userEO.setStatus(userVoIAM.getStatus()); @@ -243,11 +236,12 @@ public class SyncIAMTimer { // 固定角色数据 List roleIdList = new ArrayList<>(); - // TODO 根据level固定为一般管理人员 或 总监 + + // 配置文件写死几个账号作为管理员,不调整对应的角色 if ("1".equals(userEO.getLevelId()) || "2".equals(userEO.getLevelId()) || "3".equals(userEO.getLevelId()) || "4".equals(userEO.getLevelId())){ - roleIdList.add("1"); + roleIdList.add("4FWTB649DG"); } else { - roleIdList.add("2"); + roleIdList.add("3QD37LZJD6"); } userEO.setRoleIdList(roleIdList); diff --git a/adc-da-sys/src/main/java/com/adc/da/sync/service/controller/SyncController.java b/adc-da-sys/src/main/java/com/adc/da/sync/service/controller/SyncController.java new file mode 100644 index 0000000..3d3a587 --- /dev/null +++ b/adc-da-sys/src/main/java/com/adc/da/sync/service/controller/SyncController.java @@ -0,0 +1,95 @@ +package com.adc.da.sync.service.controller; + +import com.adc.da.sync.service.SyncIAMTimer; +import com.adc.da.sys.vo.DictQueryVo; +import com.adc.da.sys.vo.iam.CmpOrgResult; +import com.adc.da.sys.vo.iam.CmpUserResult; +import com.adc.da.util.http.ResponseMessage; +import com.adc.da.util.http.Result; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.models.auth.In; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + * 数据同步测试服务 + */ +@Slf4j +@RestController +@RequestMapping("/${restPath}/sync") +@Api(tags = {"数据同步"}) +public class SyncController { + + @Autowired + private SyncIAMTimer syncIAMTimer; + + @ApiOperation(value = "全量同步orgs") + @GetMapping("/full/orgs") + public ResponseMessage syncFullOrgs() { + int pageIndex = 1; + int pageSize = 1000; + + CmpOrgResult cmpOrgResult = this.syncIAMTimer.syncOrgIncrData(pageIndex, pageSize); + if (cmpOrgResult != null){ + int totalPages = cmpOrgResult.getData().getPages(); + for (int i = pageIndex + 1; i <= totalPages; i++){ + this.syncIAMTimer.syncOrgIncrData(i, pageSize); + } + } + + return Result.success(); + } + + @ApiOperation(value = "增量同步orgs") + @GetMapping("/incr/orgs") + public ResponseMessage syncIncrOrgs(@RequestParam Integer pageIndex, @RequestParam Integer pageSize) { + if (pageIndex == null || pageIndex == 0){ + pageIndex = 1; + } + if (pageSize == null || pageSize == 0){ + pageSize = 1000; + } + + CmpOrgResult cmpOrgResult = this.syncIAMTimer.syncOrgIncrData(pageIndex, pageSize); + return Result.success(cmpOrgResult); + } + + @ApiOperation(value = "全量同步users") + @GetMapping("/full/users") + public ResponseMessage syncFullUsers() { + int pageIndex = 1; + int pageSize = 1000; + + CmpUserResult cmpUserResult = this.syncIAMTimer.syncUserIncrData(pageIndex, pageSize, null); + if (cmpUserResult != null){ + int totalPages = cmpUserResult.getData().getPages(); + for (int i = pageIndex + 1; i <= totalPages; i++){ + this.syncIAMTimer.syncUserIncrData(i, pageSize, null); + } + } + + return Result.success(); + } + + @ApiOperation(value = "增量同步users") + @GetMapping("/incr/users") + public ResponseMessage syncIncrUsers(@RequestParam Integer pageIndex, @RequestParam Integer pageSize) { + if (pageIndex == null || pageIndex == 0){ + pageIndex = 1; + } + if (pageSize == null || pageSize == 0){ + pageSize = 1000; + } + + this.syncIAMTimer.syncUserIncrData(pageIndex, pageSize, null); + return Result.success(); + } + +} diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/dao/mysql/UserOrgEODao.java b/adc-da-sys/src/main/java/com/adc/da/sys/dao/mysql/UserOrgEODao.java index be17835..471879a 100644 --- a/adc-da-sys/src/main/java/com/adc/da/sys/dao/mysql/UserOrgEODao.java +++ b/adc-da-sys/src/main/java/com/adc/da/sys/dao/mysql/UserOrgEODao.java @@ -19,4 +19,6 @@ public interface UserOrgEODao extends BaseMapper { int insertBatch(@Param("userOrgEOList") List userOrgEOList); + void deleteBatchByUserIds(@Param("userIds") List userIds); + } diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/dao/mysql/UserRoleEODao.java b/adc-da-sys/src/main/java/com/adc/da/sys/dao/mysql/UserRoleEODao.java index 1abca18..e5c586a 100644 --- a/adc-da-sys/src/main/java/com/adc/da/sys/dao/mysql/UserRoleEODao.java +++ b/adc-da-sys/src/main/java/com/adc/da/sys/dao/mysql/UserRoleEODao.java @@ -19,4 +19,6 @@ import java.util.List; public interface UserRoleEODao extends BaseMapper { int insertBatch(@Param("userRoleEOList") List userRoleEOList); + void deleteBatchByUserIds(@Param("userIds") List userIds); + } diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/service/UserEOServiceImpl.java b/adc-da-sys/src/main/java/com/adc/da/sys/service/UserEOServiceImpl.java index e616a1a..0440713 100644 --- a/adc-da-sys/src/main/java/com/adc/da/sys/service/UserEOServiceImpl.java +++ b/adc-da-sys/src/main/java/com/adc/da/sys/service/UserEOServiceImpl.java @@ -14,14 +14,24 @@ import com.adc.da.util.exception.AdcDaBaseException; import com.adc.da.util.utils.CollectionUtils; import com.adc.da.util.utils.StringUtils; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.enums.SqlMethod; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; +import com.baomidou.mybatisplus.core.toolkit.Assert; +import com.baomidou.mybatisplus.core.toolkit.ReflectionKit; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.toolkit.SqlHelper; +import org.apache.ibatis.binding.MapperMethod; +import org.apache.ibatis.session.SqlSession; +import org.apache.poi.ss.formula.functions.T; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; @@ -42,6 +52,9 @@ public class UserEOServiceImpl implements IUserEoService { @Value("${isPassEncrypted}") private boolean isPassEncrypted; + @Value("${user.fix.role}") + private String fixUserAccount; // 同步过来需要固定角色的账号 + @Resource private UserEODao dao; @@ -128,41 +141,111 @@ public class UserEOServiceImpl implements IUserEoService { /** * 同步保存或更新 - * @param eo + * @param eoList */ @Override @Transactional(rollbackFor = Exception.class) - public void syncSaveOrUpdate(UserEO eo) { - UserEO userEO = dao.selectById(eo.getUsid()); - if (userEO == null) { - this.save(userEO); - } else { - //删除旧的角色 - QueryWrapper deleteRoleWapper =new QueryWrapper<>(); - deleteRoleWapper.eq("user_id",userEO.getUsid()); - userRoleEODao.delete(deleteRoleWapper); - - //删除旧的角色 - QueryWrapper deleteOrgWapper =new QueryWrapper<>(); - deleteOrgWapper.eq("user_id",userEO.getUsid()); - userOrgEODao.delete(deleteOrgWapper); + public void syncSaveOrUpdate(List eoList) { + if (eoList == null || eoList.isEmpty()){ + throw new AdcDaBaseException("无用户数据取回"); } - // 加入角色关联表 - eo.getRoleIdList().forEach(c -> { - UserRoleEO userRoleEO = new UserRoleEO(); - userRoleEO.setUserId(eo.getUsid()); - userRoleEO.setRoleId(c); - userRoleEODao.insert(userRoleEO); - }); + List userRoleEOList = new ArrayList<>(); + List userOrgEOList = new ArrayList<>(); - // 插入组织关联表 - eo.getOrgEOList().forEach(c -> { - UserOrgEO userOrgEO = new UserOrgEO(); - userOrgEO.setUserId(eo.getUsid()); - userOrgEO.setOrgId(c.getId()); - userOrgEODao.insert(userOrgEO); - }); + List userIds = new ArrayList<>(); + + String[] fixAccountArr = fixUserAccount.split(","); //处理固定的数据 + List fixAccountList = Arrays.asList(fixAccountArr); + + for (UserEO userEO : eoList){ + if (!fixAccountList.contains(userEO.getAccount())){ + userIds.add(userEO.getUsid()); + + // 加入角色关联表 + userEO.getRoleIdList().forEach(c -> { + UserRoleEO userRoleEO = new UserRoleEO(); + userRoleEO.setUserId(userEO.getUsid()); + userRoleEO.setRoleId(c); + if (StringUtils.isNotEmpty(userRoleEO.getRoleId())){ + userRoleEOList.add(userRoleEO); + } + }); + + // 插入组织关联表 + userEO.getOrgEOList().forEach(c -> { + UserOrgEO userOrgEO = new UserOrgEO(); + userOrgEO.setUserId(userEO.getUsid()); + userOrgEO.setOrgId(c.getId()); + if (StringUtils.isNotEmpty(userOrgEO.getOrgId())){ + userOrgEOList.add(userOrgEO); + } + }); + } + } + + this.saveOrUpdateBatch(eoList, 1000); + + //删除旧的角色 + userRoleEODao.deleteBatchByUserIds(userIds); + + //删除旧的组织 + userOrgEODao.deleteBatchByUserIds(userIds); + + // 批量插入新角色关联 + this.userRoleEODao.insertBatch(userRoleEOList); + + // 批量插入新组织关联 + this.userOrgEODao.insertBatch(userOrgEOList); + + } + + protected String sqlStatement(SqlMethod sqlMethod) { + return SqlHelper.table(UserEO.class).getSqlStatement(sqlMethod.getMethod()); + } + + private boolean saveOrUpdateBatch(List entityList, int batchSize) { + Assert.notEmpty(entityList, "error: entityList must not be empty", new Object[0]); + SqlSession batchSqlSession = SqlHelper.sqlSessionBatch(UserEO.class); + Throwable var7 = null; + + try { + int i = 0; + + for(UserEO userEO : entityList) { + + if (!com.baomidou.mybatisplus.core.toolkit.StringUtils.checkValNull(userEO.getUsid()) && !Objects.isNull(this.getUserById((userEO.getUsid())))) { + MapperMethod.ParamMap param = new MapperMethod.ParamMap(); + param.put("et", userEO); + batchSqlSession.update(this.sqlStatement(SqlMethod.UPDATE_BY_ID), param); + } else { + batchSqlSession.insert(this.sqlStatement(SqlMethod.INSERT_ONE), userEO); + } + + if (i >= 1 && i % batchSize == 0) { + batchSqlSession.flushStatements(); + } + } + + batchSqlSession.flushStatements(); + return true; + } catch (Throwable var20) { + var7 = var20; + throw var20; + } finally { + if (batchSqlSession != null) { + if (var7 != null) { + try { + batchSqlSession.close(); + } catch (Throwable var19) { + var7.addSuppressed(var19); + } + } else { + batchSqlSession.close(); + } + } + + } } @Transactional(rollbackFor = Exception.class) diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/service/iservice/IUserEoService.java b/adc-da-sys/src/main/java/com/adc/da/sys/service/iservice/IUserEoService.java index 35824d6..d01cf28 100644 --- a/adc-da-sys/src/main/java/com/adc/da/sys/service/iservice/IUserEoService.java +++ b/adc-da-sys/src/main/java/com/adc/da/sys/service/iservice/IUserEoService.java @@ -32,7 +32,7 @@ public interface IUserEoService { * 从同步处新增或编辑用户 * @param eo */ - void syncSaveOrUpdate(UserEO eo); + void syncSaveOrUpdate(List eoList); UserEO getUserById(String usid); diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpOrgInnerResult.java b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpOrgInnerResult.java new file mode 100644 index 0000000..b748ecc --- /dev/null +++ b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpOrgInnerResult.java @@ -0,0 +1,20 @@ +package com.adc.da.sys.vo.iam; + +import lombok.Data; + +import java.util.List; + +@Data +public class CmpOrgInnerResult { + + private List records; + + private int total; // 返回总条数 + + private int pageSize; + + private int pageIndex; + + private int pages; // 总页数 + +} diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpOrgResult.java b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpOrgResult.java index f60f6ab..8698058 100644 --- a/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpOrgResult.java +++ b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpOrgResult.java @@ -18,6 +18,6 @@ public class CmpOrgResult { private String traceId; - private List data; + private CmpOrgInnerResult data; } diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpUserInnerResult.java b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpUserInnerResult.java new file mode 100644 index 0000000..a647f5b --- /dev/null +++ b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpUserInnerResult.java @@ -0,0 +1,20 @@ +package com.adc.da.sys.vo.iam; + +import lombok.Data; + +import java.util.List; + +@Data +public class CmpUserInnerResult { + + private List records; + + private int total; // 返回总条数 + + private int pageSize; + + private int pageIndex; + + private int pages; // 总页数 + +} diff --git a/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpUserResult.java b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpUserResult.java index c561655..9ba315a 100644 --- a/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpUserResult.java +++ b/adc-da-sys/src/main/java/com/adc/da/sys/vo/iam/CmpUserResult.java @@ -18,6 +18,6 @@ public class CmpUserResult { private String traceId; - private List data; + private CmpUserInnerResult data; } diff --git a/adc-da-sys/src/main/resources/mybatis/mapper/sys/mysql/UserOrgEOMapper.xml b/adc-da-sys/src/main/resources/mybatis/mapper/sys/mysql/UserOrgEOMapper.xml index 14990a8..e846892 100644 --- a/adc-da-sys/src/main/resources/mybatis/mapper/sys/mysql/UserOrgEOMapper.xml +++ b/adc-da-sys/src/main/resources/mybatis/mapper/sys/mysql/UserOrgEOMapper.xml @@ -97,5 +97,13 @@ + + + delete from TR_USER_ORG + where user_id in + + #{id} + + diff --git a/adc-da-sys/src/main/resources/mybatis/mapper/sys/mysql/UserRoleEOMapper.xml b/adc-da-sys/src/main/resources/mybatis/mapper/sys/mysql/UserRoleEOMapper.xml index e65157a..a057091 100644 --- a/adc-da-sys/src/main/resources/mybatis/mapper/sys/mysql/UserRoleEOMapper.xml +++ b/adc-da-sys/src/main/resources/mybatis/mapper/sys/mysql/UserRoleEOMapper.xml @@ -97,5 +97,14 @@ + + + delete from TR_USER_ROLE + where user_id in + + #{id} + + +