From b1ccfb1b666686ff2ac3a65bbf1234bab7e01bb5 Mon Sep 17 00:00:00 2001 From: Mzaxd Date: Wed, 17 May 2023 15:45:10 +0800 Subject: [PATCH 1/3] =?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/3] =?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/3] =?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) {