mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-20 18:15:56 +08:00
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:
commit
8d5988b24d
23
pom.xml
23
pom.xml
@ -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>
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建登录用户
|
||||
*/
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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查询部门树信息
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user