From 6f5f61f6a796a6c6eda30d078f298963f6a94567 Mon Sep 17 00:00:00 2001 From: lichuanyang <1176537920@qq.com> Date: Thu, 5 Dec 2024 12:08:54 +0800 Subject: [PATCH] =?UTF-8?q?sso=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 --- .../admin/outapi/Zhuozi_SSOController.java | 72 +++++++ .../admin/outapi/vo/ZhuoziSSOLoginVO.java | 14 ++ .../admin/outapi/vo/ZhuoziSSORegisterVO.java | 14 ++ .../service/outapi/Zhuozi_SSOService.java | 19 ++ .../outapi/impl/Zhuozi_SSOServiceImpl.java | 192 ++++++++++++++++++ .../src/main/resources/application.yaml | 4 + 6 files changed, 315 insertions(+) create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/outapi/Zhuozi_SSOController.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/outapi/vo/ZhuoziSSOLoginVO.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/outapi/vo/ZhuoziSSORegisterVO.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/outapi/Zhuozi_SSOService.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/outapi/impl/Zhuozi_SSOServiceImpl.java diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/outapi/Zhuozi_SSOController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/outapi/Zhuozi_SSOController.java new file mode 100644 index 000000000..4be2594bc --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/outapi/Zhuozi_SSOController.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.system.controller.admin.outapi; + +import cn.iocoder.yudao.module.system.controller.admin.outapi.vo.*; +import cn.iocoder.yudao.module.system.service.outapi.Zhuozi_SSOService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.Map; + +@Tag(name = "管理后台 - Zhuozi_SSOController") +@RestController +@RequestMapping("/system/zhuoziSSO") +@Validated +public class Zhuozi_SSOController { + @Resource + Zhuozi_SSOService ssoService; + + @PostMapping("/login") + @Operation(summary = "login") + public Map login(@RequestBody ZhuoziSSORegisterVO registerVO) { + Map _out = new HashMap<>(); + if (registerVO != null && + ((registerVO.getAppCode() != null && !"".equals(registerVO.getAppCode().trim()) && + ssoService.getEncryptByPlatform(Zhuozi_SSOService.App_Code).equals(registerVO.getAppCode().trim())) && + (registerVO.getThirdCode() != null && !"".equals(registerVO.getThirdCode().trim()) && + ssoService.getEncryptByPlatform(Zhuozi_SSOService.Third_Code1).equals(registerVO.getThirdCode().trim())))) { + _out.put("status", 200); + _out.put("message", "成功"); + _out.put("data", new HashMap() {{ + put("token", ssoService.createToken()); + }}); + } else { + _out.put("status", 400); + _out.put("message", "登录失败,appCode或thirdCode不正确!"); + _out.put("data", ""); + } + return _out; + } + + @PostMapping("/thirdInfoLogin") + @Operation(summary = "thirdInfoLogin") + public Map thirdInfoLogin(@RequestBody ZhuoziSSOLoginVO loginVO, + @RequestHeader(value = "Authorization", required = false) String authorization) { + Map _out = new HashMap<>(); + if (!(authorization != null && !"".equals(authorization.trim()))) { + _out.put("status", 400); + _out.put("message", "登录失败,请求头[Authorization]不能为空!"); + _out.put("data", ""); + } else if (!ssoService.verifyToken(authorization.trim())) { + _out.put("status", 400); + _out.put("message", "登录失败,请求头[Authorization]值无效!"); + _out.put("data", ""); + } else { + try { + String relName = ""; + //String relName = ssoService.getDecryptByKey(loginVO.getRelName().trim(), ssoService.getEncryptByPlatform(Zhuozi_SSOService.Third_Code1)); + _out = ssoService.SSOLogin(relName, null); + } catch (Exception ex) { + System.out.println(ex.getMessage()); + _out = new HashMap<>(); + _out.put("status", 400); + _out.put("message", "登录失败,发生异常!"); + _out.put("data", ""); + } + } + return _out; + } +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/outapi/vo/ZhuoziSSOLoginVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/outapi/vo/ZhuoziSSOLoginVO.java new file mode 100644 index 000000000..6a62f0966 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/outapi/vo/ZhuoziSSOLoginVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.system.controller.admin.outapi.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - ZhuoziSSOLoginVO") +@Data +public class ZhuoziSSOLoginVO { + @Schema(description = "relName") + private String relName; + + @Schema(description = "phone") + private String phone; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/outapi/vo/ZhuoziSSORegisterVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/outapi/vo/ZhuoziSSORegisterVO.java new file mode 100644 index 000000000..aa5ea8047 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/outapi/vo/ZhuoziSSORegisterVO.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.system.controller.admin.outapi.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - ZhuoziSSORegisterVO") +@Data +public class ZhuoziSSORegisterVO { + @Schema(description = "appCode") + private String appCode; + + @Schema(description = "thirdCode") + private String thirdCode; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/outapi/Zhuozi_SSOService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/outapi/Zhuozi_SSOService.java new file mode 100644 index 000000000..7a91ced51 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/outapi/Zhuozi_SSOService.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.system.service.outapi; + +import java.util.Map; + +public interface Zhuozi_SSOService { + //属性 + String App_Code = "FLY_zhuozi_app_CFGKJghcf1165"; + String Third_Code1 = "FLY_zhuozi_app_sso_ASEvz2351xw"; + + Map SSOLogin(String relName, String phone); + + String createToken(); + + boolean verifyToken(String token); + + String getEncryptByPlatform(String KEY_PUBLIC); + + String getDecryptByKey(String plainText, String key) throws Exception; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/outapi/impl/Zhuozi_SSOServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/outapi/impl/Zhuozi_SSOServiceImpl.java new file mode 100644 index 000000000..1d656ec4b --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/outapi/impl/Zhuozi_SSOServiceImpl.java @@ -0,0 +1,192 @@ +package cn.iocoder.yudao.module.system.service.outapi.impl; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; +import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO; +import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; +import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; +import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum; +import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum; +import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2ClientConstants; +import cn.iocoder.yudao.module.system.service.logger.LoginLogService; +import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService; +import cn.iocoder.yudao.module.system.service.outapi.*; +import cn.iocoder.yudao.module.system.service.user.AdminUserService; +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.DecodedJWT; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import java.security.MessageDigest; +import java.util.*; + +@Service +public class Zhuozi_SSOServiceImpl implements Zhuozi_SSOService { + @Resource + private AdminUserService userService; + + @Resource + private LoginLogService loginLogService; + + @Resource + private OAuth2TokenService oauth2TokenService; + + //属性 + private static final long EXPIRE_DATE = 8 * 60 * 60 * 1000; //8小时 + private static final String TOKEN_SECRET = "4b5987503efda54ee658d4a712ebf605"; + + //接口方法 + @Override + public Map SSOLogin(String relName, String phone) { + Map _out = new HashMap<>(); + try { + AdminUserDO user = userService.getUserByUsername(relName); + final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME; + if (user == null) { + createLoginLog(null, relName, logTypeEnum, LoginResultEnum.BAD_CREDENTIALS); + _out.put("status", 400); + _out.put("message", "登录失败,账号不正确!"); + _out.put("data", ""); + } else if (user != null && CommonStatusEnum.isDisable(user.getStatus())) { //校验是否禁用 + createLoginLog(user.getId(), relName, logTypeEnum, LoginResultEnum.USER_DISABLED); + _out.put("status", 400); + _out.put("message", "登录失败,用户被禁用!"); + _out.put("data", ""); + } else { + createLoginLog(user.getId(), relName, logTypeEnum, LoginResultEnum.SUCCESS); + AuthLoginRespVO authLoginRespVO = null; + OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(user.getId(), getUserType().getValue(), + OAuth2ClientConstants.CLIENT_ID_DEFAULT, null); + if (accessTokenDO != null) + authLoginRespVO = AuthConvert.INSTANCE.convert(accessTokenDO); + if (authLoginRespVO != null) { + //urlStr + String accessTokenStr = ""; + String refreshTokenStr = ""; + if (authLoginRespVO.getAccessToken() != null) + accessTokenStr = authLoginRespVO.getAccessToken().trim(); + if (authLoginRespVO.getRefreshToken() != null) + refreshTokenStr = authLoginRespVO.getRefreshToken().trim(); + final String urlStr = "https://zzxmc.gw12320.com/bl/diagnosis/patientexamlistPathology?accessToken=" + accessTokenStr + "&refreshToken=" + refreshTokenStr; + //_out + _out.put("status", 200); + _out.put("message", "成功"); + _out.put("data", new HashMap() {{ + put("url", urlStr); + }}); + } else { + _out.put("status", 400); + _out.put("message", "登录失败,token生成失败!"); + _out.put("data", ""); + } + } + } catch (Exception ex) { + System.out.println(ex.getMessage()); + _out.clear(); + _out.put("status", 400); + _out.put("message", "登录失败,发生异常!"); + _out.put("data", ""); + } + return _out; + } + + @Override + public String createToken() { + String token = null; + try { + //参数 + Date date = new Date(System.currentTimeMillis() + EXPIRE_DATE); + Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET); + Map header = new HashMap<>(); + header.put("typ", "JWT"); + header.put("alg", "HS256"); + //携带信息,生成签名 + token = JWT.create().withHeader(header).withClaim("tokenid", UUID.randomUUID().toString().replace("-", "")).withExpiresAt(date).sign(algorithm); + } catch (Exception ex) { + token = null; + } + return token; + } + + @Override + public boolean verifyToken(String token) { + boolean _out = false; + if (token != null && !"".equals(token.trim())) { + try { + Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET); + JWTVerifier verifier = JWT.require(algorithm).build(); + DecodedJWT jwt = verifier.verify(token.trim()); + _out = true; + } catch (Exception ex) { + _out = false; + } + } + return _out; + } + + @Override + public String getEncryptByPlatform(String KEY_PUBLIC) { + String _temp = ""; + if (KEY_PUBLIC != null && !"".equals(KEY_PUBLIC.trim())) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] digest = md.digest(KEY_PUBLIC.trim().getBytes()); + StringBuilder sb = new StringBuilder(); + for (byte b : digest) { + sb.append(String.format("%02x", b)); + } + _temp = sb.toString().trim(); + } catch (Exception ex) { + _temp = ""; + } + } + if (_temp.length() >= 25) //length:32 + _temp = _temp.substring(8, 24); + return _temp; + } + + @Override + public String getDecryptByKey(String plainText, String key) throws Exception { + String ENCODING = "utf-8"; + String ALGORITHM = "AES"; + String PATTERN = "AES/ECB/pkcs5padding"; + SecretKey secretKey = new SecretKeySpec(key.getBytes(ENCODING), ALGORITHM); + Cipher cipher = Cipher.getInstance(PATTERN);//获取AES密码器 + cipher.init(Cipher.DECRYPT_MODE, secretKey);//初始化密码器(解密模型) + byte[] encryptData = cipher.doFinal(Base64.getDecoder().decode(plainText));//解密数据返回明文 + return new String(encryptData, ENCODING); + } + + //私有方法 + private void createLoginLog(Long userId, String username, + LoginLogTypeEnum logTypeEnum, LoginResultEnum loginResult) { + // 插入登录日志 + LoginLogCreateReqDTO reqDTO = new LoginLogCreateReqDTO(); + reqDTO.setLogType(logTypeEnum.getType()); + reqDTO.setTraceId(TracerUtils.getTraceId()); + reqDTO.setUserId(userId); + reqDTO.setUserType(getUserType().getValue()); + reqDTO.setUsername(username); + reqDTO.setUserAgent(ServletUtils.getUserAgent()); + reqDTO.setUserIp(ServletUtils.getClientIP()); + reqDTO.setResult(loginResult.getResult()); + loginLogService.createLoginLog(reqDTO); + // 更新最后登录时间 + if (userId != null && Objects.equals(LoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) { + userService.updateUserLogin(userId, ServletUtils.getClientIP()); + } + } + + private UserTypeEnum getUserType() { + return UserTypeEnum.ADMIN; + } +} diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index caada9646..b93e78e22 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -172,6 +172,8 @@ yudao: - /admin-api/tblist/patientexamlist/getplexamiddata - /admin-api/tblist/patientexamlist/insert - /admin-api/tblist/ecganalysisparas/insert + - /admin-api/system/zhuoziSSO/login + - /admin-api/system/zhuoziSSO/thirdInfoLogin websocket: enable: true # websocket的开关 path: /infra/ws # 路径 @@ -229,6 +231,8 @@ yudao: - /admin-api/tblist/patientexamlist/getplexamiddata - /admin-api/tblist/patientexamlist/insert - /admin-api/tblist/ecganalysisparas/insert + - /admin-api/system/zhuoziSSO/login + - /admin-api/system/zhuoziSSO/thirdInfoLogin ignore-tables: - system_tenant - system_tenant_package