diff --git a/pom.xml b/pom.xml index 9629c9a35..e9cf38661 100644 --- a/pom.xml +++ b/pom.xml @@ -272,6 +272,17 @@ ${lock4j.version} + + + tech.powerjob + powerjob-worker-spring-boot-starter + ${powerjob.version} + + + tech.powerjob + powerjob-official-processors + ${powerjob.version} + com.alibaba @@ -330,18 +341,6 @@ ${revision} - - - tech.powerjob - powerjob-worker-spring-boot-starter - ${powerjob.version} - - - tech.powerjob - powerjob-official-processors - ${powerjob.version} - - diff --git a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java index ff7c3b1dc..c45473474 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java @@ -1,12 +1,13 @@ package org.dromara.web.controller; import cn.dev33.satoken.annotation.SaIgnore; -import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import me.zhyd.oauth.model.AuthCallback; import me.zhyd.oauth.model.AuthResponse; import me.zhyd.oauth.model.AuthUser; import me.zhyd.oauth.request.AuthRequest; @@ -87,7 +88,7 @@ public class AuthController { } /** - * 第三方登录请求 + * 认证授权 * * @param source 登录来源 * @return 结果 @@ -98,43 +99,49 @@ public class AuthController { if (ObjectUtil.isNull(obj)) { return R.fail(source + "平台账号暂不支持"); } - AuthRequest authRequest = SocialUtils.getAuthRequest(source, socialProperties); + AuthRequest authRequest = SocialUtils.getAuthRequest(source, + obj.getClientId(), + obj.getClientSecret(), + obj.getRedirectUri()); String authorizeUrl = authRequest.authorize(AuthStateUtils.createState()); return R.ok(authorizeUrl); } /** * 第三方登录回调业务处理 - * 绑定授权 - * @param loginBody + * + * @param source 登录来源 + * @param callback 授权响应实体 * @return 结果 */ @SuppressWarnings("unchecked") - @PostMapping("/social-login") - public R socialLogin(@RequestBody LoginBody loginBody) { - // 授权类型和客户端id - String clientId = loginBody.getClientId(); - String grantType = loginBody.getGrantType(); + @GetMapping("/social-login") + public R socialLogin(String source, + String loginType, + String tenantId, + String clientId, + String grantType, + AuthCallback callback) { + SocialLoginConfigProperties obj = socialProperties.getType().get(source); + if (ObjectUtil.isNull(obj)) { + return R.fail(source + "平台账号暂不支持"); + } SysClient client = clientService.queryByClientId(clientId); // 查询不到 client 或 client 内不包含 grantType if (ObjectUtil.isNull(client) || !StringUtils.contains(client.getGrantType(), grantType)) { log.info("客户端id: {} 认证类型:{} 异常!.", clientId, grantType); return R.fail(MessageUtils.message("auth.grant.type.error")); } - // 校验租户 - loginService.checkTenant(loginBody.getTenantId()); - //判断用户登录状态,如果已经登录那么就默认为注册,如果没有登录那么默认登录 - if (!StpUtil.isLogin()) { - return R.ok(IAuthStrategy.login(loginBody, client)); - }else { - // 获取第三方登录信息 - AuthResponse response = SocialUtils.loginAuth(loginBody, socialProperties); - AuthUser authUserData = response.getData(); - // 判断授权响应是否成功 - if (!response.ok()) { - return R.fail(response.getMsg()); - } - return loginService.sociaRegister(authUserData); + AuthRequest authRequest = SocialUtils.getAuthRequest(source, + obj.getClientId(), + obj.getClientSecret(), + obj.getRedirectUri()); + AuthResponse response = authRequest.login(callback); + //判断loginType是否为login,如果是login则为登录,否则为绑定 + if (StrUtil.equals(loginType, "login")) { + return loginService.socialLogin(tenantId , response); + } else { + return loginService.sociaRegister(response); } } diff --git a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java index 84fedeab4..e56c267e6 100644 --- a/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java +++ b/ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java @@ -1,12 +1,15 @@ package org.dromara.web.service; import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.stp.SaLoginModel; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import me.zhyd.oauth.model.AuthResponse; import me.zhyd.oauth.model.AuthUser; import org.dromara.common.core.constant.Constants; import org.dromara.common.core.constant.GlobalConstants; @@ -14,14 +17,12 @@ import org.dromara.common.core.constant.TenantConstants; import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.dto.RoleDTO; import org.dromara.common.core.domain.model.LoginUser; +import org.dromara.common.core.enums.DeviceType; import org.dromara.common.core.enums.LoginType; import org.dromara.common.core.enums.TenantStatus; import org.dromara.common.core.enums.UserStatus; import org.dromara.common.core.exception.user.UserException; -import org.dromara.common.core.utils.DateUtils; -import org.dromara.common.core.utils.MessageUtils; -import org.dromara.common.core.utils.ServletUtils; -import org.dromara.common.core.utils.SpringUtils; +import org.dromara.common.core.utils.*; import org.dromara.common.log.event.LogininforEvent; import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.satoken.utils.LoginHelper; @@ -29,13 +30,13 @@ import org.dromara.common.tenant.exception.TenantException; import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.system.domain.SysUser; 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.SysUserMapper; import org.dromara.system.service.ISysPermissionService; import org.dromara.system.service.ISysSocialService; import org.dromara.system.service.ISysTenantService; -import org.dromara.web.domain.vo.LoginVo; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -69,22 +70,80 @@ public class SysLoginService { /** - * 绑定第三方用户 - * @param authUserData 授权响应实体 + * 社交登录 + * + * @param tenantId 租户id + * @param authUser 授权响应实体 * @return 统一响应实体 */ - public R sociaRegister(AuthUser authUserData ){ + public R socialLogin(String tenantId, AuthResponse authUser) { + // 判断授权响应是否成功 + if (!authUser.ok()) { + return R.fail("对不起,授权信息验证不通过,请退出重试!"); + } + AuthUser authUserData = authUser.getData(); + SysSocialVo social = sysSocialService.selectByAuthId(authUserData.getSource() + authUserData.getUuid()); + //验证授权表里面的租户id是否包含当前租户id + if (ObjectUtil.isNotNull(social) && StrUtil.isNotBlank(social.getTenantId()) + && !social.getTenantId().contains(tenantId)) { + return R.fail("对不起,你没有权限登录当前租户!"); + } + if (ObjectUtil.isNotNull(social)) { + SysUser user = userMapper.selectOne(new LambdaQueryWrapper() + .eq(SysUser::getUserId, social.getUserId())); + // 执行登录 + return loginAndRecord(user.getTenantId(), user.getUserName()); + } else { + return R.fail("你还没有绑定第三方账号,绑定后才可以登录!"); + } + } + + + /** + * 绑定第三方用户 + * @param authUser 授权响应实体 + * @return 统一响应实体 + */ + public R sociaRegister(AuthResponse authUser){ + if (!authUser.ok()) { + return R.fail("对不起,授权信息验证不通过,请退出重试!"); + } + // 判断是否已登录 + if (!StpUtil.isLogin()) { + return R.fail("授权失败,登录状态异常!"); + } + AuthUser authUserData = authUser.getData(); SysSocialBo bo = new SysSocialBo(); bo.setUserId(LoginHelper.getUserId()); bo.setAuthId(authUserData.getSource() + authUserData.getUuid()); - bo.setOpenId(authUserData.getUuid()); + bo.setSource(authUserData.getSource()); bo.setUserName(authUserData.getUsername()); - BeanUtils.copyProperties(authUserData, bo); + bo.setNickName(authUserData.getNickname()); + bo.setAvatar(authUserData.getAvatar()); + bo.setOpenId(authUserData.getUuid()); BeanUtils.copyProperties(authUserData.getToken(), bo); - sysSocialService.insertByBo(bo); - return R.ok(); + + return sysSocialService.insertByBo(bo) ? R.ok("绑定成功!"):R.fail("绑定失败!"); } + /** + * 执行登录和记录登录信息操作 + * + * @param tenantId 租户ID + * @param userName 用户名 + * @return 统一响应实体 + */ + private R loginAndRecord(String tenantId, String userName) { + checkTenant(tenantId); + SysUserVo user = loadUserByUsername(tenantId, userName); + SaLoginModel model = new SaLoginModel(); + model.setDevice(DeviceType.PC.getDevice()); + // 生成token + LoginHelper.login(buildLoginUser(user), model); + recordLogininfor(user.getTenantId(), userName, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")); + recordLoginInfo(user.getUserId()); + return R.ok( "登录成功", StpUtil.getTokenValue()); + } /** * 退出登录 @@ -120,6 +179,25 @@ public class SysLoginService { SpringUtils.context().publishEvent(logininforEvent); } + + private SysUserVo loadUserByUsername(String tenantId, String username) { + SysUser user = userMapper.selectOne(new LambdaQueryWrapper() + .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); + } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { + log.info("登录用户:{} 已被停用.", username); + throw new UserException("user.blocked", username); + } + if (TenantHelper.isEnable()) { + return userMapper.selectTenantUserByUserName(username, tenantId); + } + return userMapper.selectUserByUserName(username); + } + /** * 构建登录用户 */ diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginBody.java index cdff7738b..d399778c7 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginBody.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginBody.java @@ -3,7 +3,10 @@ package org.dromara.common.core.domain.model; import jakarta.validation.constraints.Email; import org.dromara.common.core.constant.UserConstants; import lombok.Data; -import org.dromara.common.core.validate.auth.*; +import org.dromara.common.core.validate.auth.EmailGroup; +import org.dromara.common.core.validate.auth.PasswordGroup; +import org.dromara.common.core.validate.auth.SmsGroup; +import org.dromara.common.core.validate.auth.WechatGroup; import org.hibernate.validator.constraints.Length; import jakarta.validation.constraints.NotBlank; @@ -103,18 +106,6 @@ public class LoginBody { /** * 第三方登录平台 */ - @NotBlank(message = "{social.source.not.blank}" , groups = {SocialGroup.class}) private String source; - /** - * 第三方登录code - */ - @NotBlank(message = "{social.code.not.blank}" , groups = {SocialGroup.class}) - private String socialCode; - - /** - * 第三方登录socialState - */ - @NotBlank(message = "{social.state.not.blank}" , groups = {SocialGroup.class}) - private String socialState; } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java index 374bfbf96..011254ead 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java @@ -1,11 +1,5 @@ package org.dromara.system.domain.bo; -import org.dromara.common.core.constant.UserConstants; -import org.dromara.common.core.xss.Xss; -import org.dromara.common.mybatis.core.domain.BaseEntity; -import org.dromara.common.sensitive.annotation.Sensitive; -import org.dromara.common.sensitive.core.SensitiveStrategy; -import org.dromara.system.domain.SysUser; import io.github.linpeilie.annotations.AutoMapper; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; @@ -13,8 +7,10 @@ import jakarta.validation.constraints.Size; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; - -import java.util.Date; +import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.xss.Xss; +import org.dromara.common.mybatis.core.domain.BaseEntity; +import org.dromara.system.domain.SysUser; /** * 用户信息业务对象 sys_user @@ -50,6 +46,7 @@ public class SysUserBo extends BaseEntity { * 用户昵称 */ @Xss(message = "用户昵称不能包含脚本字符") + @NotBlank(message = "用户昵称不能为空") @Size(min = 0, max = 30, message = "用户昵称长度不能超过{max}个字符") private String nickName; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDeptService.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDeptService.java index 1d3277995..b20938187 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDeptService.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDeptService.java @@ -1,7 +1,6 @@ package org.dromara.system.service; import cn.hutool.core.lang.tree.Tree; -import org.dromara.system.domain.SysDept; import org.dromara.system.domain.bo.SysDeptBo; import org.dromara.system.domain.vo.SysDeptVo; @@ -35,7 +34,7 @@ public interface ISysDeptService { * @param depts 部门列表 * @return 下拉树结构列表 */ - List> buildDeptTreeSelect(List depts); + List> buildDeptTreeSelect(List depts); /** * 根据角色ID查询部门树信息 diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java index 36680e392..874f634b8 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java @@ -70,7 +70,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { @Override public List> selectDeptTreeList(SysDeptBo bo) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); - List depts = baseMapper.selectList(lqw); + List depts = baseMapper.selectDeptList(lqw); return buildDeptTreeSelect(depts); } @@ -93,7 +93,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService { * @return 下拉树结构列表 */ @Override - public List> buildDeptTreeSelect(List depts) { + public List> buildDeptTreeSelect(List depts) { if (CollUtil.isEmpty(depts)) { return CollUtil.newArrayList(); }