疯狂的狮子Li
2023-06-20 9448782f451790beb05b2e6717683dc0a59d6a24
ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java
@@ -6,7 +6,6 @@
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthResponse;
@@ -33,21 +32,18 @@
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.common.web.config.properties.CaptchaProperties;
import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.bo.SocialUserBo;
import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.domain.vo.SocialUserVo;
import org.dromara.system.domain.bo.SysSocialBo;
import org.dromara.system.domain.vo.SysSocialVo;
import org.dromara.system.domain.vo.SysTenantVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.mapper.SocialUserMapper;
import org.dromara.system.mapper.SysUserMapper;
import org.dromara.system.service.ISocialUserService;
import org.dromara.system.service.ISysSocialService;
import org.dromara.system.service.ISysPermissionService;
import org.dromara.system.service.ISysTenantService;
import org.dromara.system.service.ISysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.time.Duration;
import java.util.Date;
import java.util.List;
@@ -64,8 +60,7 @@
public class SysLoginService {
    private final SysUserMapper userMapper;
    private final ISocialUserService socialUserService;
    private final ISysUserService userService;
    private final ISysSocialService sysSocialService;
    private final CaptchaProperties captchaProperties;
    private final ISysPermissionService permissionService;
    private final ISysTenantService tenantService;
@@ -172,36 +167,54 @@
     *
     * @param source   登录来源
     * @param authUser 授权响应实体
     * @param request  Http请求对象
     * @return 统一响应实体
     */
    public R<String> socialLogin(String source, AuthResponse<AuthUser> authUser, HttpServletRequest request) throws IOException {
    public R<String> socialLogin(String source, AuthResponse<AuthUser> authUser) {
        // 判断授权响应是否成功
        if (!authUser.ok()) {
            return R.fail("对不起,授权信息验证不通过,请退出重试!");
        }
        AuthUser authUserData = authUser.getData();
        // 查询社交用户信息,判断是否已经绑定,如果已经绑定则直接登录,否则验证是否登录,未登录则先登录再绑定
        SocialUserVo user = socialUserService.selectSocialUserByAuthId(source + authUserData.getUuid());
        SysSocialVo user = sysSocialService.selectByAuthId(authUserData.getSource() + authUserData.getUuid());
        if (ObjectUtil.isNotNull(user)) {
            checkTenant(user.getTenantId());
            SysUserVo dbUser = loadUserByUsername(user.getTenantId(), user.getUserName());
            LoginHelper.loginByDevice(buildLoginUser(dbUser), DeviceType.SOCIAL);
            recordLogininfor(dbUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
            recordLoginInfo(user.getUserId());
            // 执行登录和记录登录信息操作
            return loginAndRecord(user.getTenantId(), user.getUserName(), authUserData);
        } else {
            // 判断是否已登录
            if (LoginHelper.getUserId() == null) {
                return R.fail("授权失败,请先登录再绑定");
                return R.fail("授权失败,请先登录才能绑定");
            }
            SocialUserBo socialUserBo = new SocialUserBo();
            socialUserService.insertByBo(setAuthUserData(authUserData, socialUserBo));
            SysUserVo lodingData = loadUserByUsername(LoginHelper.getTenantId(), LoginHelper.getUsername());
            checkTenant(lodingData.getTenantId());
            LoginHelper.loginByDevice(buildLoginUser(lodingData), DeviceType.SOCIAL);
            recordLogininfor(lodingData.getTenantId(), socialUserBo.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
            recordLoginInfo(socialUserBo.getUserId());
            SysSocialBo bo = new SysSocialBo();
            bo.setUserId(LoginHelper.getUserId());
            bo.setAuthId(authUserData.getSource() + authUserData.getUuid());
            bo.setSource(authUserData.getSource());
            bo.setUserName(authUserData.getUsername());
            bo.setNickName(authUserData.getNickname());
            bo.setAvatar(authUserData.getAvatar());
            bo.setOpenId(authUserData.getUuid());
            BeanUtils.copyProperties(authUserData.getToken(), bo);
            sysSocialService.insertByBo(bo);
            SysUserVo sysUser = loadUserByUsername(LoginHelper.getTenantId(), LoginHelper.getUsername());
            // 执行登录和记录登录信息操作
            return loginAndRecord(sysUser.getTenantId(), sysUser.getUserName(), authUserData);
        }
    }
    /**
     * 执行登录和记录登录信息操作
     *
     * @param tenantId 租户ID
     * @param userName 用户名
     * @param authUser 授权用户信息
     * @return 统一响应实体
     */
    private R<String> loginAndRecord(String tenantId, String userName, AuthUser authUser) {
        checkTenant(tenantId);
        SysUserVo dbUser = loadUserByUsername(tenantId, userName);
        LoginHelper.loginByDevice(buildLoginUser(dbUser), DeviceType.SOCIAL);
        recordLogininfor(dbUser.getTenantId(), userName, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
        recordLoginInfo(dbUser.getUserId());
        return R.ok(StpUtil.getTokenValue());
    }
@@ -322,7 +335,7 @@
    private SysUserVo loadUserByEmail(String tenantId, String email) {
        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
            .select(SysUser::getPhonenumber, SysUser::getStatus)
            .select(SysUser::getEmail, SysUser::getStatus)
            .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
            .eq(SysUser::getEmail, email));
        if (ObjectUtil.isNull(user)) {
@@ -391,25 +404,24 @@
        String errorKey = GlobalConstants.PWD_ERR_CNT_KEY + username;
        String loginFail = Constants.LOGIN_FAIL;
        // 获取用户登录错误次数(可自定义限制策略 例如: key + username + ip)
        Integer errorNumber = RedisUtils.getCacheObject(errorKey);
        // 获取用户登录错误次数,默认为0 (可自定义限制策略 例如: key + username + ip)
        int errorNumber = ObjectUtil.defaultIfNull(RedisUtils.getCacheObject(errorKey), 0);
        // 锁定时间内登录 则踢出
        if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(maxRetryCount)) {
        if (errorNumber >= maxRetryCount) {
            recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
            throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
        }
        if (supplier.get()) {
            // 是否第一次
            errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1;
            // 错误次数递增
            errorNumber++;
            RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
            // 达到规定错误次数 则锁定登录
            if (errorNumber.equals(maxRetryCount)) {
                RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
            if (errorNumber >= maxRetryCount) {
                recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
                throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
            } else {
                // 未达到规定错误次数 则递增
                RedisUtils.setCacheObject(errorKey, errorNumber);
                // 未达到规定错误次数
                recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber));
                throw new UserException(loginType.getRetryLimitCount(), errorNumber);
            }
@@ -440,29 +452,4 @@
        }
    }
    public SocialUserBo setAuthUserData(AuthUser authUserData, SocialUserBo socialUser) {
        socialUser.setUserId(LoginHelper.getUserId());
        socialUser.setAuthId(authUserData.getSource() + authUserData.getUuid());
        socialUser.setSource(authUserData.getSource());
        socialUser.setUserName(authUserData.getUsername());
        socialUser.setNickName(authUserData.getNickname());
        socialUser.setAvatar(authUserData.getAvatar());
        socialUser.setEmail(authUserData.getEmail());
        socialUser.setOpenId(authUserData.getUuid());
        socialUser.setAccessToken(authUserData.getToken().getAccessToken());
        socialUser.setExpireIn(authUserData.getToken().getExpireIn());
        socialUser.setRefreshToken(authUserData.getToken().getRefreshToken());
        socialUser.setAccessCode(authUserData.getToken().getAccessCode());
        socialUser.setUnionId(authUserData.getToken().getUnionId());
        socialUser.setScope(authUserData.getToken().getScope());
        socialUser.setTokenType(authUserData.getToken().getTokenType());
        socialUser.setIdToken(authUserData.getToken().getIdToken());
        socialUser.setMacAlgorithm(authUserData.getToken().getMacAlgorithm());
        socialUser.setMacKey(authUserData.getToken().getMacKey());
        socialUser.setCode(authUserData.getToken().getCode());
        socialUser.setOauthToken(authUserData.getToken().getOauthToken());
        socialUser.setOauthTokenSecret(authUserData.getToken().getOauthTokenSecret());
        return socialUser;
    }
}