thiszhc
2023-06-16 aec0e227479de49213185ff6bb98d4e99b35eb8b
ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java
@@ -32,13 +32,19 @@
import org.dromara.common.tenant.exception.TenantException;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.common.web.config.properties.CaptchaProperties;
import org.dromara.system.domain.SysAuthUser;
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.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.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;
@@ -59,6 +65,8 @@
public class SysLoginService {
    private final SysUserMapper userMapper;
    private final ISocialUserService socialUserService;
    private final ISysUserService userService;
    private final CaptchaProperties captchaProperties;
    private final ISysPermissionService permissionService;
    private final ISysTenantService tenantService;
@@ -160,64 +168,65 @@
        return StpUtil.getTokenValue();
    }
    /**
     * 认证授权登录
     * @param source
     * @throws IOException
     */
    /**
     * 社交登录
     *
     * @param source   登录来源
     * @param authUser   授权响应实体
     * @param request   Http请求对象
     * @return   统一响应实体
     * @throws IOException
     * @param authUser 授权响应实体
     * @param request  Http请求对象
     * @return 统一响应实体
     */
    public R<String> socialLogin(String source, AuthResponse<AuthUser> authUser, HttpServletRequest request) throws IOException {
        // 判断授权响应是否成功
        if (!authUser.ok()) {
            return R.fail("对不起,授权信息验证不通过,请联系管理员");
            return R.fail("对不起,授权信息验证不通过,请退出重试!");
        }
        AuthUser authUserData = authUser.getData();
        // 判断数据库中是否已存在该用户
        SysUserVo user = userMapper.selectAuthUserByUuid(source + authUserData.getUuid());
        String authId = source + authUserData.getUuid();
        SocialUserVo user = socialUserService.selectSocialUserByAuthId(authId);
        if (ObjectUtil.isNotNull(user)) {
            checkTenant(user.getTenantId());
            SysUserVo dbUser = loadUserByUsername(user.getTenantId(), user.getUserName());
            // 登录
            LoginHelper.loginByDevice(buildLoginUser(dbUser), DeviceType.auth);
            recordLogininfor(dbUser.getTenantId(), user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
            recordLoginInfo(user.getUserId());
            return R.ok(StpUtil.getTokenValue());
            //执行登录和记录登录信息操作
            return loginAndRecord(user.getTenantId(), user.getUserName(), authUserData);
        } else {
            // 判断是否已登录
            if (LoginHelper.getUserId() == null) {
                return R.fail("授权失败,请先登录再绑定");
            }
            // 组装授权用户信息
            SysAuthUser sysAuthUser = new SysAuthUser();
            sysAuthUser.setAvatar(authUserData.getAvatar());
            sysAuthUser.setUuid(source + authUserData.getUuid());
            sysAuthUser.setUserId(LoginHelper.getUserId());
            sysAuthUser.setUserName(authUserData.getUsername());
            sysAuthUser.setNickName(authUserData.getNickname());
            sysAuthUser.setEmail(authUserData.getEmail());
            sysAuthUser.setSource(source);
            sysAuthUser.setCreateTime(new Date().toString());
            // 新用户,绑定第三方账号
            userMapper.insertAuthUser(sysAuthUser);
            SocialUserBo socialUserBo = new SocialUserBo();
            socialUserBo.setUserId(LoginHelper.getUserId());
            socialUserBo.setAuthId(authUserData.getSource() + authUserData.getUuid());
            socialUserBo.setSource(authUserData.getSource());
            socialUserBo.setUserName(authUserData.getUsername());
            socialUserBo.setNickName(authUserData.getNickname());
            socialUserBo.setAvatar(authUserData.getAvatar());
            socialUserBo.setOpenId(authUserData.getUuid());
            BeanUtils.copyProperties(authUserData, socialUserBo);
            BeanUtils.copyProperties(authUserData.getToken(), socialUserBo);
            socialUserService.insertByBo(socialUserBo);
            SysUserVo lodingData = loadUserByUsername(LoginHelper.getTenantId(), LoginHelper.getUsername());
            checkTenant(lodingData.getTenantId());
            LoginHelper.loginByDevice(buildLoginUser(lodingData), DeviceType.auth);
            recordLogininfor(lodingData.getTenantId(), sysAuthUser.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
            recordLoginInfo(sysAuthUser.getUserId());
            return R.ok(StpUtil.getTokenValue());
            //执行登录和记录登录信息操作
            return loginAndRecord(lodingData.getTenantId(), socialUserBo.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());
    }
    /**
     * 退出登录
@@ -300,9 +309,9 @@
    private SysUserVo loadUserByUsername(String tenantId, String username) {
        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .select(SysUser::getUserName, SysUser::getStatus)
                .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
                .eq(SysUser::getUserName, username));
            .select(SysUser::getUserName, SysUser::getStatus)
            .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
            .eq(SysUser::getUserName, username));
        if (ObjectUtil.isNull(user)) {
            log.info("登录用户:{} 不存在.", username);
            throw new UserException("user.not.exists", username);
@@ -318,9 +327,9 @@
    private SysUserVo loadUserByPhonenumber(String tenantId, String phonenumber) {
        SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .select(SysUser::getPhonenumber, SysUser::getStatus)
                .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
                .eq(SysUser::getPhonenumber, phonenumber));
            .select(SysUser::getPhonenumber, SysUser::getStatus)
            .eq(TenantHelper.isEnable(), SysUser::getTenantId, tenantId)
            .eq(SysUser::getPhonenumber, phonenumber));
        if (ObjectUtil.isNull(user)) {
            log.info("登录用户:{} 不存在.", phonenumber);
            throw new UserException("user.not.exists", phonenumber);
@@ -336,7 +345,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)) {
@@ -405,25 +414,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);
            }
@@ -448,7 +456,7 @@
            log.info("登录租户:{} 已被停用.", tenantId);
            throw new TenantException("tenant.blocked");
        } else if (ObjectUtil.isNotNull(tenant.getExpireTime())
                && new Date().after(tenant.getExpireTime())) {
            && new Date().after(tenant.getExpireTime())) {
            log.info("登录租户:{} 已超过有效期.", tenantId);
            throw new TenantException("tenant.expired");
        }