|
@@ -1,9 +1,15 @@
|
|
|
package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl;
|
|
|
|
|
|
-import cn.hutool.json.JSONUtil;
|
|
|
-import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthThirdLoginReqVO;
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLogin2ReqVO;
|
|
|
+import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLoginReqVO;
|
|
|
+import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysSocialUserDO;
|
|
|
+import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.user.SysSocialUserMapper;
|
|
|
+import cn.iocoder.yudao.adminserver.modules.system.dal.redis.auth.SysAuthSocialUserRedisDAO;
|
|
|
import cn.iocoder.yudao.adminserver.modules.system.enums.user.SysUserSocialTypeEnum;
|
|
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
|
|
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
|
|
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
|
|
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
|
|
import cn.iocoder.yudao.framework.security.core.LoginUser;
|
|
@@ -40,6 +46,8 @@ 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;
|
|
|
|
|
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
|
@@ -58,6 +66,7 @@ public class SysAuthServiceImpl implements SysAuthService {
|
|
|
@Resource
|
|
|
@Lazy // 延迟加载,因为存在相互依赖的问题
|
|
|
private AuthenticationManager authenticationManager;
|
|
|
+
|
|
|
@Resource
|
|
|
private SysUserService userService;
|
|
|
@Resource
|
|
@@ -69,6 +78,11 @@ public class SysAuthServiceImpl implements SysAuthService {
|
|
|
@Resource
|
|
|
private SysUserSessionService userSessionService;
|
|
|
|
|
|
+ @Resource
|
|
|
+ private SysAuthSocialUserRedisDAO authSocialUserRedisDAO;
|
|
|
+ @Resource
|
|
|
+ private SysSocialUserMapper socialUserMapper;
|
|
|
+
|
|
|
@Resource
|
|
|
private AuthRequestFactory authRequestFactory;
|
|
|
|
|
@@ -109,24 +123,6 @@ public class SysAuthServiceImpl implements SysAuthService {
|
|
|
return userSessionService.createUserSession(loginUser, userIp, userAgent);
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public String thirdLogin(SysAuthThirdLoginReqVO reqVO, String userIp, String userAgent) {
|
|
|
- // 使用 code 授权码,进行登陆
|
|
|
- AuthRequest authRequest = authRequestFactory.get(SysUserSocialTypeEnum.valueOfType(reqVO.getType()).getSource());
|
|
|
- AuthCallback authCallback = SysAuthConvert.INSTANCE.convert(reqVO);
|
|
|
- AuthResponse<?> authResponse = authRequest.login(authCallback);
|
|
|
- log.info("[thirdLogin][请求三方平台 type({}) request({}) response({})]", reqVO.getType(), JsonUtils.toJsonString(authCallback),
|
|
|
- JsonUtils.toJsonString(authResponse));
|
|
|
- if (!authResponse.ok()) {
|
|
|
- throw new RuntimeException(""); // TODO 芋艿:补全
|
|
|
- }
|
|
|
- AuthUser authUser = (AuthUser) authResponse.getData();
|
|
|
-
|
|
|
- // 查找到对应的
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
private void verifyCaptcha(String username, String captchaUUID, String captchaCode) {
|
|
|
String code = captchaService.getCaptchaCode(captchaUUID);
|
|
|
// 验证码不存在
|
|
@@ -190,6 +186,124 @@ public class SysAuthServiceImpl implements SysAuthService {
|
|
|
return permissionService.getUserRoleIds(userId, singleton(CommonStatusEnum.ENABLE.getStatus()));
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public String socialLogin(SysAuthSocialLoginReqVO reqVO, String userIp, String userAgent) {
|
|
|
+ // 使用 code 授权码,进行登陆
|
|
|
+ AuthCallback authCallback = SysAuthConvert.INSTANCE.convert(reqVO);
|
|
|
+ AuthUser authUser = this.obtainAuthUserFromCache(reqVO.getType(), authCallback);
|
|
|
+
|
|
|
+ // 如果未绑定 SysSocialUserDO 用户,则无法自动登陆,进行报错
|
|
|
+ String unionId = getAuthUserUnionId(authUser);
|
|
|
+ List<SysSocialUserDO> socialUsers = socialUserMapper.selectListByTypeAndUnionId(UserTypeEnum.ADMIN.getValue(),
|
|
|
+ reqVO.getType(), unionId);
|
|
|
+ if (CollUtil.isEmpty(socialUsers)) {
|
|
|
+ throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用账号密码,进行登陆。
|
|
|
+ SysUserDO user = userService.getUser(socialUsers.get(0).getUserId());
|
|
|
+ if (user == null) {
|
|
|
+ throw exception(USER_NOT_EXISTS);
|
|
|
+ }
|
|
|
+ LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
|
|
|
+ // TODO 芋艿:需要改造下,增加各种登陆方式
|
|
|
+ loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
|
|
|
+
|
|
|
+ // 保存社交用户
|
|
|
+ this.saveSocialUser(reqVO.getType(), socialUsers, loginUser.getId(), authUser);
|
|
|
+
|
|
|
+ // 缓存登陆用户到 Redis 中,返回 sessionId 编号
|
|
|
+ return userSessionService.createUserSession(loginUser, userIp, userAgent);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String socialLogin2(SysAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) {
|
|
|
+ // 使用 code 授权码,进行登陆
|
|
|
+ AuthCallback authCallback = SysAuthConvert.INSTANCE.convert(reqVO);
|
|
|
+ AuthUser authUser = this.obtainAuthUserFromCache(reqVO.getType(), authCallback);
|
|
|
+
|
|
|
+ // 查询社交对应的 SysSocialUserDO 用户
|
|
|
+ String unionId = getAuthUserUnionId(authUser);
|
|
|
+ List<SysSocialUserDO> socialUsers = socialUserMapper.selectListByTypeAndUnionId(UserTypeEnum.ADMIN.getValue(),
|
|
|
+ reqVO.getType(), unionId);
|
|
|
+
|
|
|
+ // 使用账号密码,进行登陆。
|
|
|
+ LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword()); // TODO 芋艿:需要改造下,增加各种登陆方式
|
|
|
+ loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
|
|
|
+
|
|
|
+ // 保存社交用户
|
|
|
+ this.saveSocialUser(reqVO.getType(), socialUsers, loginUser.getId(), authUser);
|
|
|
+
|
|
|
+ // 缓存登陆用户到 Redis 中,返回 sessionId 编号
|
|
|
+ return userSessionService.createUserSession(loginUser, userIp, userAgent);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String getAuthUserUnionId(AuthUser authUser) {
|
|
|
+ return StrUtil.blankToDefault(authUser.getToken().getUnionId(), authUser.getUuid());
|
|
|
+ }
|
|
|
+
|
|
|
+ private AuthUser obtainAuthUserFromCache(Integer type, AuthCallback authCallback) {
|
|
|
+ // 从缓存中获取
|
|
|
+ AuthUser authUser = authSocialUserRedisDAO.get(type, authCallback);
|
|
|
+ if (authUser != null) {
|
|
|
+ return authUser;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 请求获取
|
|
|
+ authUser = this.obtainAuthUser(type, authCallback);
|
|
|
+ authSocialUserRedisDAO.set(type, authCallback, authUser);
|
|
|
+ return authUser;
|
|
|
+ }
|
|
|
+
|
|
|
+ private AuthUser obtainAuthUser(Integer type, AuthCallback authCallback) {
|
|
|
+ AuthRequest authRequest = authRequestFactory.get(SysUserSocialTypeEnum.valueOfType(type).getSource());
|
|
|
+ AuthResponse<?> authResponse = authRequest.login(authCallback);
|
|
|
+ log.info("[obtainAuthUser][请求三方平台 type({}) request({}) response({})]", type, JsonUtils.toJsonString(authCallback),
|
|
|
+ JsonUtils.toJsonString(authResponse));
|
|
|
+ if (!authResponse.ok()) {
|
|
|
+ throw exception(AUTH_THIRD_OAUTH_FAILURE, authResponse.getMsg());
|
|
|
+ }
|
|
|
+ return (AuthUser) authResponse.getData();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存社交用户
|
|
|
+ *
|
|
|
+ * @param socialUsers 已存在的社交用户列表
|
|
|
+ * @param userId 绑定的用户编号
|
|
|
+ * @param authUser 需要保存的社交用户信息
|
|
|
+ */
|
|
|
+ private void saveSocialUser(Integer type, List<SysSocialUserDO> socialUsers, Long userId, AuthUser authUser) {
|
|
|
+ // 逻辑一:如果 socialUsers 指定的 userId 改变,需要进行更新
|
|
|
+ // 例如说,一个微信 unionId 对应了多个社交账号,结果其中有个关联了新的 userId,则其它也要跟着修改
|
|
|
+ // 考虑到 socialUsers 一般比较少,直接 for 循环更新即可
|
|
|
+ socialUsers.forEach(socialUser -> {
|
|
|
+ if (Objects.equals(socialUser.getUserId(), userId)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ socialUserMapper.updateById(new SysSocialUserDO().setUserId(socialUser.getUserId()).setUserId(userId));
|
|
|
+ });
|
|
|
+
|
|
|
+ // 逻辑二:如果 authUser 不存在于 socialUsers 中,则进行新增;否则,进行更新
|
|
|
+ SysSocialUserDO saveSocialUser = CollUtil.findOneByField(socialUsers, "openid", authUser.getUuid());
|
|
|
+ if (saveSocialUser == null) {
|
|
|
+ saveSocialUser = new SysSocialUserDO();
|
|
|
+ saveSocialUser.setUserId(userId).setUserType(UserTypeEnum.ADMIN.getValue());
|
|
|
+ saveSocialUser.setType(type).setOpenid(authUser.getUuid()).setToken(authUser.getToken().getAccessToken())
|
|
|
+ .setUnionId(getAuthUserUnionId(authUser)).setRawTokenInfo(JsonUtils.toJsonString(authUser.getToken()));
|
|
|
+ saveSocialUser.setNickname(authUser.getNickname()).setAvatar(authUser.getAvatar())
|
|
|
+ .setRawUserInfo(JsonUtils.toJsonString(authUser.getRawUserInfo()));
|
|
|
+ socialUserMapper.insert(saveSocialUser);
|
|
|
+ } else {
|
|
|
+ saveSocialUser = new SysSocialUserDO().setId(saveSocialUser.getId());
|
|
|
+ saveSocialUser.setToken(authUser.getToken().getAccessToken()).setUnionId(getAuthUserUnionId(authUser))
|
|
|
+ .setRawTokenInfo(JsonUtils.toJsonString(authUser.getToken()));
|
|
|
+ saveSocialUser.setNickname(authUser.getNickname()).setAvatar(authUser.getAvatar())
|
|
|
+ .setRawUserInfo(JsonUtils.toJsonString(authUser.getRawUserInfo()));
|
|
|
+ socialUserMapper.updateById(saveSocialUser);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public void logout(String token) {
|
|
|
// 查询用户信息
|