Merge remote-tracking branch 'origin/5.X' into justauth

# Conflicts:
#	ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java
#	ruoyi-admin/src/main/java/org/dromara/web/service/SysLoginService.java
#	ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/model/LoginBody.java
This commit is contained in:
thiszhc 2023-07-01 15:21:24 +08:00
commit 8d5988b24d
7 changed files with 144 additions and 73 deletions

23
pom.xml
View File

@ -272,6 +272,17 @@
<version>${lock4j.version}</version>
</dependency>
<!-- PowerJob -->
<dependency>
<groupId>tech.powerjob</groupId>
<artifactId>powerjob-worker-spring-boot-starter</artifactId>
<version>${powerjob.version}</version>
</dependency>
<dependency>
<groupId>tech.powerjob</groupId>
<artifactId>powerjob-official-processors</artifactId>
<version>${powerjob.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
@ -330,18 +341,6 @@
<version>${revision}</version>
</dependency>
<!-- PowerJob -->
<dependency>
<groupId>tech.powerjob</groupId>
<artifactId>powerjob-worker-spring-boot-starter</artifactId>
<version>${powerjob.version}</version>
</dependency>
<dependency>
<groupId>tech.powerjob</groupId>
<artifactId>powerjob-official-processors</artifactId>
<version>${powerjob.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -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<LoginVo> socialLogin(@RequestBody LoginBody loginBody) {
// 授权类型和客户端id
String clientId = loginBody.getClientId();
String grantType = loginBody.getGrantType();
@GetMapping("/social-login")
public R<String> 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<AuthUser> 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<AuthUser> response = authRequest.login(callback);
//判断loginType是否为login,如果是login则为登录否则为绑定
if (StrUtil.equals(loginType, "login")) {
return loginService.socialLogin(tenantId , response);
} else {
return loginService.sociaRegister(response);
}
}

View File

@ -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<LoginVo> sociaRegister(AuthUser authUserData ){
public R<String> socialLogin(String tenantId, AuthResponse<AuthUser> 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<SysUser>()
.eq(SysUser::getUserId, social.getUserId()));
// 执行登录
return loginAndRecord(user.getTenantId(), user.getUserName());
} else {
return R.fail("你还没有绑定第三方账号,绑定后才可以登录!");
}
}
/**
* 绑定第三方用户
* @param authUser 授权响应实体
* @return 统一响应实体
*/
public R<String> sociaRegister(AuthResponse<AuthUser> 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<String> 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<SysUser>()
.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);
}
/**
* 构建登录用户
*/

View File

@ -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;
}

View File

@ -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;

View File

@ -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<Tree<Long>> buildDeptTreeSelect(List<SysDept> depts);
List<Tree<Long>> buildDeptTreeSelect(List<SysDeptVo> depts);
/**
* 根据角色ID查询部门树信息

View File

@ -70,7 +70,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService {
@Override
public List<Tree<Long>> selectDeptTreeList(SysDeptBo bo) {
LambdaQueryWrapper<SysDept> lqw = buildQueryWrapper(bo);
List<SysDept> depts = baseMapper.selectList(lqw);
List<SysDeptVo> depts = baseMapper.selectDeptList(lqw);
return buildDeptTreeSelect(depts);
}
@ -93,7 +93,7 @@ public class SysDeptServiceImpl implements ISysDeptService, DeptService {
* @return 下拉树结构列表
*/
@Override
public List<Tree<Long>> buildDeptTreeSelect(List<SysDept> depts) {
public List<Tree<Long>> buildDeptTreeSelect(List<SysDeptVo> depts) {
if (CollUtil.isEmpty(depts)) {
return CollUtil.newArrayList();
}