diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java index bca6b170b..323827d4f 100644 --- a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java @@ -26,10 +26,10 @@ public interface AuthConvert { return convert0(bean).setUserType(UserTypeEnum.MEMBER.getValue()); } - SocialUserBindReqDTO convert(Long userId, Integer value, AppAuthSocialBindReqVO reqVO); - SocialUserBindReqDTO convert(Long userId, Integer value, AppAuthSocialLogin2ReqVO reqVO); - SocialUserBindReqDTO convert(Long userId, Integer value, AppAuthSocialLoginReqVO reqVO); - SocialUserUnbindReqDTO convert(Long userId, Integer value, AppAuthSocialUnbindReqVO reqVO); + SocialUserBindReqDTO convert(Long userId, Integer userType, AppAuthSocialBindReqVO reqVO); + SocialUserBindReqDTO convert(Long userId, Integer userType, AppAuthSocialLogin2ReqVO reqVO); + SocialUserBindReqDTO convert(Long userId, Integer userType, AppAuthSocialLoginReqVO reqVO); + SocialUserUnbindReqDTO convert(Long userId, Integer userType, AppAuthSocialUnbindReqVO reqVO); SmsCodeSendReqDTO convert(AppAuthSendSmsReqVO reqVO); SmsCodeUseReqDTO convert(AppAuthResetPasswordReqVO reqVO, SmsSceneEnum scene, String usedIp); diff --git a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java index 5fd8db9b9..fcb68b271 100644 --- a/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java +++ b/yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java @@ -152,6 +152,7 @@ public class MemberAuthServiceImpl implements MemberAuthService { @Override public void socialBind(Long userId, AppAuthSocialBindReqVO reqVO) { + // 绑定社交用户(新增) socialUserApi.bindSocialUser(AuthConvert.INSTANCE.convert(userId, getUserType().getValue(), reqVO)); } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java index 94e4cfaba..02a7942bb 100644 --- a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java @@ -3,15 +3,11 @@ package cn.iocoder.yudao.module.system.api.social; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; import cn.iocoder.yudao.module.system.service.social.SocialUserService; -import me.zhyd.oauth.model.AuthUser; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SOCIAL_USER_NOT_FOUND; - /** * 社交用户的 API 实现类 * @@ -31,16 +27,7 @@ public class SocialUserApiImpl implements SocialUserApi { @Override public void bindSocialUser(SocialUserBindReqDTO reqDTO) { - // 使用 code 授权 - AuthUser authUser = socialUserService.getAuthUser(reqDTO.getType(), reqDTO.getCode(), - reqDTO.getState()); - if (authUser == null) { - throw exception(SOCIAL_USER_NOT_FOUND); - } - - // 绑定社交用户(新增) - socialUserService.bindSocialUser(reqDTO.getUserId(), reqDTO.getUserType(), - reqDTO.getType(), authUser); + socialUserService.bindSocialUser(reqDTO); } @Override @@ -51,21 +38,12 @@ public class SocialUserApiImpl implements SocialUserApi { @Override public void checkSocialUser(Integer type, String code, String state) { - AuthUser authUser = socialUserService.getAuthUser(type, code, state); - if (authUser == null) { - throw exception(SOCIAL_USER_NOT_FOUND); - } + socialUserService.checkSocialUser(type, code, state); } @Override public Long getBindUserId(Integer userType, Integer type, String code, String state) { - AuthUser authUser = socialUserService.getAuthUser(type, code, state); - if (authUser == null) { - throw exception(SOCIAL_USER_NOT_FOUND); - } - - // - return null; + return socialUserService.getBindUserId(userType, type, code, state); } } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java index e4cce5100..c52328cc0 100644 --- a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java @@ -1,14 +1,15 @@ package cn.iocoder.yudao.module.system.convert.auth; -import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthMenuRespVO; -import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthPermissionInfoRespVO; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.*; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.enums.permission.MenuIdEnum; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.security.core.LoginUser; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; @@ -71,4 +72,9 @@ public interface AuthConvert { return CollectionUtils.filterList(treeNodeMap.values(), node -> MenuIdEnum.ROOT.getId().equals(node.getParentId())); } + SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialBindReqVO reqVO); + SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialLogin2ReqVO reqVO); + SocialUserBindReqDTO convert(Long userId, Integer userType, AuthSocialLoginReqVO reqVO); + SocialUserUnbindReqDTO convert(Long userId, Integer userType, AuthSocialUnbindReqVO reqVO); + } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java index d2fe1ba1a..f237049bd 100644 --- a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.service.auth; -import cn.hutool.core.collection.CollUtil; 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; @@ -12,7 +11,6 @@ import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthSocialBi import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthSocialLogin2ReqVO; import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthSocialLoginReqVO; import cn.iocoder.yudao.module.system.convert.auth.AuthConvert; -import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; 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; @@ -37,7 +35,6 @@ import org.springframework.stereotype.Service; import org.springframework.util.Assert; import javax.annotation.Resource; -import java.util.List; import java.util.Objects; import java.util.Set; @@ -70,7 +67,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { @Resource private UserSessionService userSessionService; @Resource - private SocialUserService socialService; + private SocialUserService socialUserService; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { @@ -192,19 +189,15 @@ public class AdminAuthServiceImpl implements AdminAuthService { @Override public String socialLogin(AuthSocialLoginReqVO reqVO, String userIp, String userAgent) { - // 使用 code 授权码,进行登录 - AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState()); - Assert.notNull(authUser, "授权用户不为空"); - - // 如果未绑定 SocialUserDO 用户,则无法自动登录,进行报错 - String unionId = socialService.getAuthUserUnionId(authUser); - List socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, getUserType().getValue()); - if (CollUtil.isEmpty(socialUsers)) { + // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 + Long userId = socialUserService.getBindUserId(UserTypeEnum.MEMBER.getValue(), reqVO.getType(), + reqVO.getCode(), reqVO.getState()); + if (userId == null) { throw exception(AUTH_THIRD_LOGIN_NOT_BIND); } // 自动登录 - AdminUserDO user = userService.getUser(socialUsers.get(0).getUserId()); + AdminUserDO user = userService.getUser(userId); if (user == null) { throw exception(USER_NOT_EXISTS); } @@ -214,7 +207,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { LoginUser loginUser = this.buildLoginUser(user); // 绑定社交用户(更新) - socialService.bindSocialUser(loginUser.getId(), getUserType().getValue(), reqVO.getType(), authUser); + socialUserService.bindSocialUser(AuthConvert.INSTANCE.convert(loginUser.getId(), getUserType().getValue(), reqVO)); // 缓存登录用户到 Redis 中,返回 sessionId 编号 return userSessionService.createUserSession(loginUser, userIp, userAgent); @@ -223,14 +216,14 @@ public class AdminAuthServiceImpl implements AdminAuthService { @Override public String socialLogin2(AuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) { // 使用 code 授权码,进行登录 - AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState()); + AuthUser authUser = socialUserService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState()); Assert.notNull(authUser, "授权用户不为空"); // 使用账号密码,进行登录。 LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword()); // 绑定社交用户(新增) - socialService.bindSocialUser(loginUser.getId(), getUserType().getValue(), reqVO.getType(), authUser); + socialUserService.bindSocialUser(AuthConvert.INSTANCE.convert(loginUser.getId(), getUserType().getValue(), reqVO)); // 缓存登录用户到 Redis 中,返回 sessionId 编号 return userSessionService.createUserSession(loginUser, userIp, userAgent); @@ -238,12 +231,8 @@ public class AdminAuthServiceImpl implements AdminAuthService { @Override public void socialBind(Long userId, AuthSocialBindReqVO reqVO) { - // 使用 code 授权码,进行登录 - AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState()); - Assert.notNull(authUser, "授权用户不为空"); - // 绑定社交用户(新增) - socialService.bindSocialUser(userId, getUserType().getValue(), reqVO.getType(), authUser); + socialUserService.bindSocialUser(AuthConvert.INSTANCE.convert(userId, getUserType().getValue(), reqVO)); } @Override diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java index b7a7d00d7..f57baff0d 100644 --- a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java @@ -2,10 +2,12 @@ package cn.iocoder.yudao.module.system.service.social; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import me.zhyd.oauth.model.AuthUser; +import javax.validation.Valid; import javax.validation.constraints.NotNull; import java.util.List; @@ -47,17 +49,6 @@ public interface SocialUserService { return StrUtil.blankToDefault(authUser.getToken().getUnionId(), authUser.getUuid()); } - /** - * 获得 unionId 对应的某个社交平台的“所有”社交用户 - * 注意,这里的“所有”,指的是类似【微信】平台,包括了小程序、公众号、PC 网站,他们的 unionId 是一致的 - * - * @param type 社交平台的类型 {@link SocialTypeEnum} - * @param unionId 社交平台的 unionId - * @param userType 全局用户类型 - * @return 社交用户列表 - */ - List getAllSocialUserList(Integer type, String unionId, Integer userType); - /** * 获得指定用户的社交用户列表 * @@ -69,12 +60,10 @@ public interface SocialUserService { /** * 绑定社交用户 - * @param userId 用户编号 - * @param userType 用户类型 - * @param type 社交平台的类型 {@link SocialTypeEnum} - * @param authUser 授权用户 + * + * @param reqDTO 绑定信息 */ - void bindSocialUser(Long userId, Integer userType, Integer type, AuthUser authUser); + void bindSocialUser(@Valid SocialUserBindReqDTO reqDTO); /** * 取消绑定社交用户 @@ -86,4 +75,27 @@ public interface SocialUserService { */ void unbindSocialUser(Long userId, Integer userType, Integer type, String unionId); + /** + * 校验社交用户的认证信息是否正确 + * 如果校验不通过,则抛出 {@link ServiceException} 业务异常 + * + * @param type 社交平台的类型 + * @param code 授权码 + * @param state state + */ + void checkSocialUser(Integer type, String code, String state); + + /** + * 获得社交用户的绑定用户编号 + * 注意,返回的是 MemberUser 或者 AdminUser 的 id 编号! + * 该方法会执行和 {@link #checkSocialUser(Integer, String, String)} 一样的逻辑。 + * 所以在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常 + * + * @param userType 用户类型 + * @param type 社交平台的类型 + * @param code 授权码 + * @param state state + * @return 绑定用户编号 + */ + Long getBindUserId(Integer userType, Integer type, String code, String state); } diff --git a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java index 533f7fdf9..b408a1fd4 100644 --- a/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.service.social; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.http.HttpUtils; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserMapper; import cn.iocoder.yudao.module.system.dal.redis.social.SocialAuthUserRedisDAO; @@ -25,8 +26,7 @@ import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SOCIAL_USER_AUTH_FAILURE; -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SOCIAL_USER_UNBIND_NOT_SELF; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; /** * 社交用户 Service 实现类 @@ -72,8 +72,16 @@ public class SocialUserServiceImpl implements SocialUserService { return authUser; } - @Override - public List getAllSocialUserList(Integer type, String unionId, Integer userType) { + /** + * 获得 unionId 对应的某个社交平台的“所有”社交用户 + * 注意,这里的“所有”,指的是类似【微信】平台,包括了小程序、公众号、PC 网站,他们的 unionId 是一致的 + * + * @param type 社交平台的类型 {@link SocialTypeEnum} + * @param unionId 社交平台的 unionId + * @param userType 全局用户类型 + * @return 社交用户列表 + */ + private List getAllSocialUserList(Integer type, String unionId, Integer userType) { List types = SocialTypeEnum.getRelationTypes(type); return socialUserMapper.selectListByTypeAndUnionId(userType, types, unionId); } @@ -84,8 +92,28 @@ public class SocialUserServiceImpl implements SocialUserService { } @Override + public void bindSocialUser(SocialUserBindReqDTO reqDTO) { + // 使用 code 授权 + AuthUser authUser = getAuthUser(reqDTO.getType(), reqDTO.getCode(), + reqDTO.getState()); + if (authUser == null) { + throw exception(SOCIAL_USER_NOT_FOUND); + } + + // 绑定社交用户(新增) + bindSocialUser(reqDTO.getUserId(), reqDTO.getUserType(), + reqDTO.getType(), authUser); + } + + /** + * 绑定社交用户 + * @param userId 用户编号 + * @param userType 用户类型 + * @param type 社交平台的类型 {@link SocialTypeEnum} + * @param authUser 授权用户 + */ @Transactional(rollbackFor = Exception.class) - public void bindSocialUser(Long userId, Integer userType, Integer type, AuthUser authUser) { + protected void bindSocialUser(Long userId, Integer userType, Integer type, AuthUser authUser) { // 获得 unionId 对应的 SocialUserDO 列表 String unionId = getAuthUserUnionId(authUser); List socialUsers = this.getAllSocialUserList(type, unionId, userType); @@ -137,6 +165,30 @@ public class SocialUserServiceImpl implements SocialUserService { socialUserMapper.deleteBatchIds(CollectionUtils.convertSet(socialUsers, SocialUserDO::getId)); } + @Override + public void checkSocialUser(Integer type, String code, String state) { + AuthUser authUser = getAuthUser(type, code, state); + if (authUser == null) { + throw exception(SOCIAL_USER_NOT_FOUND); + } + } + + @Override + public Long getBindUserId(Integer userType, Integer type, String code, String state) { + AuthUser authUser = getAuthUser(type, code, state); + if (authUser == null) { + throw exception(SOCIAL_USER_NOT_FOUND); + } + + // 如果未绑定 SocialUserDO 用户,则无法自动登录,进行报错 + String unionId = getAuthUserUnionId(authUser); + List socialUsers = getAllSocialUserList(type, unionId, userType); + if (CollUtil.isEmpty(socialUsers)) { + throw exception(AUTH_THIRD_LOGIN_NOT_BIND); + } + return socialUsers.get(0).getUserId(); + } + @VisibleForTesting public void unbindOldSocialUser(Long userId, Integer userType, Integer type, String newUnionId) { List types = SocialTypeEnum.getRelationTypes(type);