diff --git a/pom.xml b/pom.xml
index 6b4ce3d..d2d6c9f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -56,6 +56,8 @@
3.1.1
3.0.2
+
+ 1.16.6
3.2.2
@@ -343,6 +345,13 @@
jsr305
${jsr305.version}
+
+
+
+ me.zhyd.oauth
+ JustAuth
+ ${justauth.version}
+
diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
index 36079d1..50dd58b 100644
--- a/ruoyi-admin/pom.xml
+++ b/ruoyi-admin/pom.xml
@@ -31,6 +31,12 @@
mysql-connector-j
+
+
+ com.ruoyi
+ ruoyi-common-social
+
+
org.postgresql
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
index 6c3b286..5bb5581 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
@@ -15,7 +15,7 @@ public class RuoYiApplication
public static void main(String[] args)
{
SpringApplication.run(RuoYiApplication.class, args);
- System.out.println("(♥◠‿◠)ノ゙ RuoYi-Flex启动成功 ლ(´ڡ`ლ)゙ \n" +
+ System.out.println("(♥◠‿◠)ノ゙ RuoYi-Flex-Boot启动成功 ლ(´ڡ`ლ)゙ \n" +
" ███████ ██ ██ ██ ████████ ██ \n" +
"░██░░░░██ ░░██ ██ ░░ ░██░░░░░ ░██ \n" +
"░██ ░██ ██ ██ ██████ ░░████ ██ ░██ ░██ █████ ██ ██\n" +
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/AuthController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/AuthController.java
index 4ca7575..6872415 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/AuthController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/AuthController.java
@@ -7,18 +7,25 @@ import com.mybatisflex.core.query.QueryWrapper;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.core.domain.AjaxResult;
import com.ruoyi.common.core.core.domain.model.LoginUser;
+import com.ruoyi.common.core.core.domain.model.SocialLoginBody;
import com.ruoyi.common.core.utils.*;
import com.ruoyi.common.encrypt.annotation.ApiEncrypt;
import com.ruoyi.common.json.utils.JsonUtils;
import com.ruoyi.common.security.utils.LoginHelper;
+import com.ruoyi.common.social.config.properties.SocialLoginConfigProperties;
+import com.ruoyi.common.social.config.properties.SocialProperties;
+import com.ruoyi.common.social.utils.SocialUtils;
import com.ruoyi.common.tenant.helper.TenantHelper;
+import com.ruoyi.common.websocket.utils.WebSocketUtils;
import com.ruoyi.system.domain.bo.SysTenantBo;
+import com.ruoyi.system.domain.vo.SysClientVo;
import com.ruoyi.system.domain.vo.SysTenantVo;
import com.ruoyi.system.domain.vo.SysUserVo;
import com.ruoyi.system.service.*;
import com.ruoyi.web.domain.vo.LoginTenantVo;
import com.ruoyi.web.domain.vo.LoginVo;
import com.ruoyi.web.domain.vo.TenantListVo;
+import com.ruoyi.web.service.SysRegisterService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
@@ -29,12 +36,17 @@ import com.ruoyi.common.core.core.domain.model.RegisterBody;
import com.ruoyi.system.domain.SysClient;
import com.ruoyi.web.service.IAuthStrategy;
import com.ruoyi.web.service.SysLoginService;
+import me.zhyd.oauth.model.AuthResponse;
+import me.zhyd.oauth.model.AuthUser;
+import me.zhyd.oauth.request.AuthRequest;
+import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.net.URL;
import java.util.List;
-import java.util.Set;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
import static com.ruoyi.system.domain.table.SysClientTableDef.SYS_CLIENT;
@@ -46,7 +58,6 @@ import static com.ruoyi.system.domain.table.SysClientTableDef.SYS_CLIENT;
*/
@Slf4j
@SaIgnore
-@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/auth")
@@ -57,7 +68,16 @@ public class AuthController {
@Resource
private ISysClientService clientService;
@Resource
+ private SysRegisterService registerService;
+ @Resource
+ private ISysConfigService configService;
+ @Resource
private ISysTenantService tenantService;
+ @Resource
+ private ISysSocialService socialService;
+
+ private final ScheduledExecutorService scheduledExecutorService;
+ private final SocialProperties socialProperties;
/**
* 登录方法
@@ -74,7 +94,7 @@ public class AuthController {
String clientId = loginBody.getClientId();
String grantType = loginBody.getGrantType();
QueryWrapper query=QueryWrapper.create().from(SYS_CLIENT).where(SYS_CLIENT.CLIENT_ID.eq(clientId));
- SysClient client = clientService.getOne(query);
+ SysClientVo client = clientService.getOneAs(query,SysClientVo.class);
// 查询不到 client 或 client 内不包含 grantType
if (ObjectUtil.isNull(client) || !StringUtils.contains(client.getGrantType(), grantType)) {
log.info("客户端id: {} 认证类型:{} 异常!.", clientId, grantType);
@@ -86,7 +106,64 @@ public class AuthController {
loginService.checkTenant(loginBody.getTenantId());
// 登录
- return R.ok(IAuthStrategy.login(body, client, grantType));
+ LoginVo loginVo =IAuthStrategy.login(body, client, grantType);
+
+ Long userId = LoginHelper.getUserId();
+ scheduledExecutorService.schedule(() -> {
+ WebSocketUtils.sendMessage(userId, "欢迎登录RuoYi-Flex多租户管理系统");
+ }, 3, TimeUnit.SECONDS);
+
+ return R.ok(loginVo);
+ }
+
+ /**
+ * 第三方登录请求
+ *
+ * @param source 登录来源
+ * @return 结果
+ */
+ @GetMapping("/binding/{source}")
+ public R authBinding(@PathVariable("source") String source) {
+ SocialLoginConfigProperties obj = socialProperties.getType().get(source);
+ if (ObjectUtil.isNull(obj)) {
+ return R.fail(source + "平台账号暂不支持");
+ }
+ AuthRequest authRequest = SocialUtils.getAuthRequest(source, socialProperties);
+ String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
+ return R.ok("操作成功", authorizeUrl);
+ }
+
+ /**
+ * 第三方登录回调业务处理 绑定授权
+ *
+ * @param loginBody 请求体
+ * @return 结果
+ */
+ @PostMapping("/social/callback")
+ public R socialCallback(@RequestBody SocialLoginBody loginBody) {
+ // 获取第三方登录信息
+ AuthResponse response = SocialUtils.loginAuth(
+ loginBody.getSource(), loginBody.getSocialCode(),
+ loginBody.getSocialState(), socialProperties);
+ AuthUser authUserData = response.getData();
+ // 判断授权响应是否成功
+ if (!response.ok()) {
+ return R.fail(response.getMsg());
+ }
+ loginService.socialRegister(authUserData);
+ return R.ok();
+ }
+
+
+ /**
+ * 取消授权
+ *
+ * @param socialId socialId
+ */
+ @DeleteMapping(value = "/unlock/{socialId}")
+ public R unlockSocial(@PathVariable Long socialId) {
+ Boolean rows = socialService.deleteWithValidById(socialId);
+ return rows ? R.ok() : R.fail("取消授权失败");
}
/**
@@ -103,12 +180,12 @@ public class AuthController {
*/
@PostMapping("/register")
public R register(@Validated @RequestBody RegisterBody user) {
- //if (!configService.selectRegisterEnabled(user.getTenantId())) // TODO:注册代码
+ if (!configService.selectRegisterEnabled(user.getTenantId()))
{
return R.fail("当前系统没有开启注册功能!");
}
-// registerService.register(user);
-// return R.ok();
+ registerService.register(user);
+ return R.ok();
}
/**
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/IAuthStrategy.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/IAuthStrategy.java
index ed11904..5b88d85 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/service/IAuthStrategy.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/IAuthStrategy.java
@@ -6,6 +6,7 @@ import com.ruoyi.common.core.core.domain.model.LoginBody;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.system.domain.SysClient;
+import com.ruoyi.system.domain.vo.SysClientVo;
import com.ruoyi.web.domain.vo.LoginVo;
/**
@@ -19,8 +20,13 @@ public interface IAuthStrategy {
/**
* 登录
+ *
+ * @param body 登录对象
+ * @param client 授权管理视图对象
+ * @param grantType 授权类型
+ * @return 登录验证信息
*/
- static LoginVo login(String body, SysClient client, String grantType) {
+ static LoginVo login(String body, SysClientVo client, String grantType) {
// 授权类型和客户端id
String beanName = grantType + BASE_NAME;
if (!SpringUtils.containsBean(beanName)) {
@@ -32,7 +38,11 @@ public interface IAuthStrategy {
/**
* 登录
+ *
+ * @param body 登录对象
+ * @param client 授权管理视图对象
+ * @return 登录验证信息
*/
- LoginVo login(String body, SysClient client);
+ LoginVo login(String body, SysClientVo client);
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/SysLoginService.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/SysLoginService.java
index 7f28f15..e76230e 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/service/SysLoginService.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/SysLoginService.java
@@ -3,6 +3,7 @@ package com.ruoyi.web.service;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.mybatisflex.core.tenant.TenantManager;
import com.ruoyi.common.core.constant.*;
@@ -18,14 +19,18 @@ import com.ruoyi.common.security.utils.LoginHelper;
import com.ruoyi.common.tenant.exception.TenantException;
import com.ruoyi.common.tenant.helper.TenantHelper;
import com.ruoyi.system.domain.SysUser;
+import com.ruoyi.system.domain.bo.SysSocialBo;
import com.ruoyi.system.domain.bo.SysUserBo;
+import com.ruoyi.system.domain.vo.SysSocialVo;
import com.ruoyi.system.domain.vo.SysTenantVo;
import com.ruoyi.system.domain.vo.SysUserVo;
import com.ruoyi.system.service.ISysPermissionService;
+import com.ruoyi.system.service.ISysSocialService;
import com.ruoyi.system.service.ISysTenantService;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import me.zhyd.oauth.model.AuthUser;
import org.springframework.beans.factory.annotation.Autowired;
import com.ruoyi.common.core.core.domain.model.LoginUser;
import com.ruoyi.common.core.utils.DateUtils;
@@ -59,12 +64,66 @@ public class SysLoginService {
@Resource
private ISysPermissionService permissionService;
+ @Resource
+ private ISysSocialService sysSocialService;
+
@Resource
private ISysUserService userService;
@Resource
private ISysTenantService tenantService;
+ /**
+ * 绑定第三方用户
+ *
+ * @param authUserData 授权响应实体
+ * @return 统一响应实体
+ */
+ public void socialRegister(AuthUser authUserData) {
+ String authId = authUserData.getSource() + authUserData.getUuid();
+ // 第三方用户信息
+ SysSocialBo bo = BeanUtil.toBean(authUserData, SysSocialBo.class);
+ BeanUtil.copyProperties(authUserData.getToken(), bo);
+ bo.setUserId(LoginHelper.getUserId());
+ bo.setAuthId(authId);
+ bo.setOpenId(authUserData.getUuid());
+ bo.setUserName(authUserData.getUsername());
+ bo.setNickName(authUserData.getNickname());
+ // 查询是否已经绑定用户
+ List list = sysSocialService.selectListByAuthId(authId);
+ if (CollUtil.isEmpty(list)) {
+ // 没有绑定用户, 新增用户信息
+ sysSocialService.insertByBo(bo);
+ } else {
+ // 更新用户信息
+ bo.setSocialId(list.get(0).getSocialId());
+ sysSocialService.updateByBo(bo);
+ }
+ }
+
+ /**
+ * 退出登录
+ */
+ public void logout() {
+ try {
+ LoginUser loginUser = LoginHelper.getLoginUser();
+ if (ObjectUtil.isNull(loginUser)) {
+ return;
+ }
+ if (LoginHelper.isSuperAdmin()) {
+ // 超级管理员 登出清除动态租户
+ TenantHelper.clearDynamic();
+ }
+ recordLogininfor(loginUser.getTenantId(), loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
+ } catch (NotLoginException ignored) {
+ } finally {
+ try {
+ StpUtil.logout();
+ } catch (NotLoginException ignored) {
+ }
+ }
+ }
+
/**
* 登录校验
*/
@@ -180,25 +239,18 @@ public class SysLoginService {
}
/**
- * 退出登录
+ * 记录登录信息
+ *
+ * @param userId 用户ID
*/
- public void logout() {
- try {
- LoginUser loginUser = LoginHelper.getLoginUser();
- if (ObjectUtil.isNull(loginUser)) {
- return;
- }
- if (LoginHelper.isSuperAdmin()) {
- // 超级管理员 登出清除动态租户
- TenantHelper.clearDynamic();
- }
- recordLogininfor(loginUser.getTenantId(), loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
- } catch (NotLoginException ignored) {
- } finally {
- try {
- StpUtil.logout();
- } catch (NotLoginException ignored) {
- }
- }
+ public void recordLoginInfo(Long userId, String ip) {
+ SysUser sysUser = new SysUser();
+ sysUser.setUserId(userId);
+ sysUser.setLoginIp(ip);
+ sysUser.setLoginDate(DateUtils.getNowDate());
+ sysUser.setUpdateBy(userId);
+ userService.updateById(sysUser);
}
+
+
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/SysRegisterService.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/SysRegisterService.java
index 44a0352..b1ede30 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/service/SysRegisterService.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/SysRegisterService.java
@@ -8,6 +8,7 @@ import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.common.log.event.LogininforEvent;
import com.ruoyi.common.redis.utils.RedisUtils;
+import com.ruoyi.common.tenant.helper.TenantHelper;
import com.ruoyi.common.web.config.properties.CaptchaProperties;
import com.ruoyi.system.domain.SysUser;
import com.ruoyi.system.domain.bo.SysUserBo;
@@ -30,8 +31,7 @@ import org.springframework.stereotype.Service;
*/
@RequiredArgsConstructor
@Service
-public class SysRegisterService
-{
+public class SysRegisterService {
@Resource
private ISysUserService userService;
@@ -43,33 +43,36 @@ public class SysRegisterService
/**
* 注册
*/
- public void register(RegisterBody registerBody)
- {
+ public void register(RegisterBody registerBody) {
Long tenantId = registerBody.getTenantId();
- String username = registerBody.getUsername();
- String password = registerBody.getPassword();
- // 校验用户类型是否存在
- String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
+ TenantHelper.dynamic(tenantId, () -> {
+ String username = registerBody.getUsername();
+ String password = registerBody.getPassword();
+ // 校验用户类型是否存在
+ String userType = UserType.getUserType(registerBody.getUserType()).getUserType();
- boolean captchaEnabled = captchaProperties.getEnable();
- // 验证码开关
- if (captchaEnabled) {
- validateCaptcha(tenantId, username, registerBody.getCode(), registerBody.getUuid());
- }
- SysUserBo sysUser = new SysUserBo();
- sysUser.setUserName(username);
- sysUser.setNickName(username);
- sysUser.setPassword(BCrypt.hashpw(password));
- sysUser.setUserType(userType);
+ boolean captchaEnabled = captchaProperties.getEnable();
+ // 验证码开关
+ if (captchaEnabled) {
+ validateCaptcha(tenantId, username, registerBody.getCode(), registerBody.getUuid());
+ }
+ SysUserBo sysUser = new SysUserBo();
+ sysUser.setUserName(username);
+ sysUser.setNickName(username);
+ sysUser.setPassword(BCrypt.hashpw(password));
+ sysUser.setUserType(userType);
- if (!userService.checkUserNameUnique(sysUser)) {
- throw new UserException("user.register.save.error", username);
- }
- boolean regFlag = userService.registerUser(sysUser, tenantId);
- if (!regFlag) {
- throw new UserException("user.register.error");
- }
- recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success"));
+ boolean unique = userService.checkUserNameUnique(sysUser);
+
+ if (!unique) {
+ throw new UserException("user.register.save.error", username);
+ }
+ boolean regFlag = userService.registerUser(sysUser, tenantId);
+ if (!regFlag) {
+ throw new UserException("user.register.error");
+ }
+ recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success"));
+ });
}
/**
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/EmailAuthStrategy.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/EmailAuthStrategy.java
index 79201ef..41ec96c 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/EmailAuthStrategy.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/EmailAuthStrategy.java
@@ -3,10 +3,10 @@ package com.ruoyi.web.service.impl;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
-import com.ruoyi.common.core.core.domain.AjaxResult;
import com.ruoyi.common.core.core.domain.model.EmailLoginBody;
import com.ruoyi.common.json.utils.JsonUtils;
import com.ruoyi.common.tenant.helper.TenantHelper;
+import com.ruoyi.system.domain.vo.SysClientVo;
import com.ruoyi.system.domain.vo.SysUserVo;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.domain.vo.LoginVo;
@@ -15,7 +15,6 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.GlobalConstants;
-import com.ruoyi.common.core.core.domain.model.LoginBody;
import com.ruoyi.common.core.core.domain.model.LoginUser;
import com.ruoyi.common.core.enums.LoginType;
import com.ruoyi.common.core.enums.UserStatus;
@@ -24,12 +23,8 @@ import com.ruoyi.common.core.exception.user.UserException;
import com.ruoyi.common.core.utils.MessageUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.ValidatorUtils;
-import com.ruoyi.common.core.validate.auth.EmailGroup;
import com.ruoyi.common.redis.utils.RedisUtils;
import com.ruoyi.common.security.utils.LoginHelper;
-import com.ruoyi.system.domain.SysClient;
-import com.ruoyi.system.domain.SysUser;
-import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.web.service.IAuthStrategy;
import com.ruoyi.web.service.SysLoginService;
import org.springframework.stereotype.Service;
@@ -48,8 +43,9 @@ public class EmailAuthStrategy implements IAuthStrategy {
private final SysLoginService loginService;
@Resource
private ISysUserService userService;
+
@Override
- public LoginVo login(String body, SysClient client) {
+ public LoginVo login(String body, SysClientVo client) {
EmailLoginBody loginBody = JsonUtils.parseObject(body, EmailLoginBody.class);
ValidatorUtils.validate(loginBody);
Long tenantId = loginBody.getTenantId();
@@ -97,17 +93,15 @@ public class EmailAuthStrategy implements IAuthStrategy {
}
private SysUserVo loadUserByEmail(Long tenantId, String email) {
- return TenantHelper.dynamic(tenantId, () -> {
- SysUserVo user =userService.selectUserByEmail(email);
- if (ObjectUtil.isNull(user)) {
- log.info("登录用户:{} 不存在.", email);
- throw new UserException("user.not.exists", email);
- } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
- log.info("登录用户:{} 已被停用.", email);
- throw new UserException("user.blocked", email);
- }
- return user;
- });
+ SysUserVo user = userService.selectTenantUserByEmail(tenantId, email);
+ if (ObjectUtil.isNull(user)) {
+ log.info("登录用户:{} 不存在.", email);
+ throw new UserException("user.not.exists", email);
+ } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
+ log.info("登录用户:{} 已被停用.", email);
+ throw new UserException("user.blocked", email);
+ }
+ return user;
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/PasswordAuthStrategy.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/PasswordAuthStrategy.java
index 7037a64..e44f0e0 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/PasswordAuthStrategy.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/PasswordAuthStrategy.java
@@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.core.core.domain.model.PasswordLoginBody;
import com.ruoyi.common.json.utils.JsonUtils;
import com.ruoyi.common.tenant.helper.TenantHelper;
+import com.ruoyi.system.domain.vo.SysClientVo;
import com.ruoyi.system.service.ISysUserService;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
@@ -49,7 +50,7 @@ public class PasswordAuthStrategy implements IAuthStrategy {
private ISysUserService userService;
@Override
- public LoginVo login(String body, SysClient client) {
+ public LoginVo login(String body, SysClientVo client) {
PasswordLoginBody loginBody = JsonUtils.parseObject(body, PasswordLoginBody.class);
ValidatorUtils.validate(loginBody);
Long tenantId = loginBody.getTenantId();
@@ -80,8 +81,8 @@ public class PasswordAuthStrategy implements IAuthStrategy {
// 生成token
LoginHelper.login(loginUser, model);
- loginService.recordLogininfor(loginUser.getTenantId(), username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
- loginService.recordLoginInfo(user.getUserId(),user.getVersion());
+// loginService.recordLogininfor(loginUser.getTenantId(), username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));
+// loginService.recordLoginInfo(user.getUserId(),user.getVersion());
LoginVo loginVo = new LoginVo();
loginVo.setAccessToken(StpUtil.getTokenValue());
@@ -113,8 +114,7 @@ public class PasswordAuthStrategy implements IAuthStrategy {
}
private SysUserVo loadUserByUsername(Long tenantId, String username) {
-
- SysUserVo user = userService.selectTenantUserByUserName(username,tenantId);
+ SysUserVo user = userService.selectTenantUserByUserName(tenantId,username);
if (ObjectUtil.isNull(user)) {
log.info("登录用户:{} 不存在.", username);
throw new UserException("user.not.exists", username);
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/SmsAuthStrategy.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/SmsAuthStrategy.java
new file mode 100644
index 0000000..62a7933
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/SmsAuthStrategy.java
@@ -0,0 +1,103 @@
+package com.ruoyi.web.service.impl;
+
+import cn.dev33.satoken.stp.SaLoginModel;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.ruoyi.common.core.core.domain.model.LoginUser;
+import com.ruoyi.common.core.core.domain.model.SmsLoginBody;
+import com.ruoyi.system.service.ISysUserService;
+import jakarta.annotation.Resource;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import com.ruoyi.common.core.constant.Constants;
+import com.ruoyi.common.core.constant.GlobalConstants;
+import com.ruoyi.common.core.enums.LoginType;
+import com.ruoyi.common.core.enums.UserStatus;
+import com.ruoyi.common.core.exception.user.CaptchaExpireException;
+import com.ruoyi.common.core.exception.user.UserException;
+import com.ruoyi.common.core.utils.MessageUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.ValidatorUtils;
+import com.ruoyi.common.json.utils.JsonUtils;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import com.ruoyi.common.security.utils.LoginHelper;
+import com.ruoyi.system.domain.vo.SysClientVo;
+import com.ruoyi.system.domain.vo.SysUserVo;
+import com.ruoyi.web.domain.vo.LoginVo;
+import com.ruoyi.web.service.IAuthStrategy;
+import com.ruoyi.web.service.SysLoginService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 短信认证策略
+ *
+ * @author Michelle.Chung
+ */
+@Slf4j
+@Service("sms" + IAuthStrategy.BASE_NAME)
+@RequiredArgsConstructor
+public class SmsAuthStrategy implements IAuthStrategy {
+
+ @Resource
+ private SysLoginService loginService;
+ @Resource
+ private ISysUserService userService;
+
+ @Override
+ public LoginVo login(String body, SysClientVo client) {
+ SmsLoginBody loginBody = JsonUtils.parseObject(body, SmsLoginBody.class);
+ ValidatorUtils.validate(loginBody);
+ Long tenantId = loginBody.getTenantId();
+ String phonenumber = loginBody.getPhonenumber();
+ String smsCode = loginBody.getSmsCode();
+
+ // 通过手机号查找用户
+ SysUserVo user = loadUserByPhonenumber(tenantId, phonenumber);
+
+ loginService.checkLogin(LoginType.SMS, tenantId, user.getUserName(), () -> !validateSmsCode(tenantId, phonenumber, smsCode));
+ // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
+ LoginUser loginUser = loginService.buildLoginUser(user);
+ loginUser.setClientKey(client.getClientKey());
+ loginUser.setDeviceType(client.getDeviceType());
+ SaLoginModel model = new SaLoginModel();
+ model.setDevice(client.getDeviceType());
+ // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
+ // 例如: 后台用户30分钟过期 app用户1天过期
+ model.setTimeout(client.getTimeout());
+ model.setActiveTimeout(client.getActiveTimeout());
+ model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
+ // 生成token
+ LoginHelper.login(loginUser, model);
+
+ LoginVo loginVo = new LoginVo();
+ loginVo.setAccessToken(StpUtil.getTokenValue());
+ loginVo.setExpireIn(StpUtil.getTokenTimeout());
+ loginVo.setClientId(client.getClientId());
+ return loginVo;
+ }
+
+ /**
+ * 校验短信验证码
+ */
+ private boolean validateSmsCode(Long tenantId, String phonenumber, String smsCode) {
+ String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + phonenumber);
+ if (StringUtils.isBlank(code)) {
+ loginService.recordLogininfor(tenantId, phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
+ throw new CaptchaExpireException();
+ }
+ return code.equals(smsCode);
+ }
+
+ private SysUserVo loadUserByPhonenumber(Long tenantId, String phonenumber) {
+ SysUserVo user = userService.selectTenantUserByPhonenumber(tenantId, phonenumber);
+ if (ObjectUtil.isNull(user)) {
+ log.info("登录用户:{} 不存在.", phonenumber);
+ throw new UserException("user.not.exists", phonenumber);
+ } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
+ log.info("登录用户:{} 已被停用.", phonenumber);
+ throw new UserException("user.blocked", phonenumber);
+ }
+ return user;
+ }
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/SocialAuthStrategy.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/SocialAuthStrategy.java
new file mode 100644
index 0000000..d1c0075
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/SocialAuthStrategy.java
@@ -0,0 +1,122 @@
+package com.ruoyi.web.service.impl;
+
+import cn.dev33.satoken.stp.SaLoginModel;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.http.Method;
+import com.ruoyi.system.service.ISysUserService;
+import jakarta.annotation.Resource;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import me.zhyd.oauth.model.AuthResponse;
+import me.zhyd.oauth.model.AuthUser;
+import com.ruoyi.common.core.core.domain.model.LoginUser;
+import com.ruoyi.common.core.core.domain.model.SocialLoginBody;
+import com.ruoyi.common.core.enums.UserStatus;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.exception.user.UserException;
+import com.ruoyi.common.core.utils.ValidatorUtils;
+import com.ruoyi.common.json.utils.JsonUtils;
+import com.ruoyi.common.security.utils.LoginHelper;
+import com.ruoyi.common.social.config.properties.SocialProperties;
+import com.ruoyi.common.social.utils.SocialUtils;
+import com.ruoyi.common.tenant.helper.TenantHelper;
+import com.ruoyi.system.domain.vo.SysClientVo;
+import com.ruoyi.system.domain.vo.SysSocialVo;
+import com.ruoyi.system.domain.vo.SysUserVo;
+import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.system.service.ISysSocialService;
+import com.ruoyi.web.domain.vo.LoginVo;
+import com.ruoyi.web.service.IAuthStrategy;
+import com.ruoyi.web.service.SysLoginService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 第三方授权策略
+ *
+ * @author thiszhc is 三三
+ */
+@Slf4j
+@Service("social" + IAuthStrategy.BASE_NAME)
+@RequiredArgsConstructor
+public class SocialAuthStrategy implements IAuthStrategy {
+
+ private final SocialProperties socialProperties;
+ @Resource
+ private ISysSocialService sysSocialService;
+ @Resource
+ private ISysUserService userService;
+ @Resource
+ private SysLoginService loginService;
+
+ /**
+ * 登录-第三方授权登录
+ *
+ * @param body 登录信息
+ * @param client 客户端信息
+ */
+ @Override
+ public LoginVo login(String body, SysClientVo client) {
+ SocialLoginBody loginBody = JsonUtils.parseObject(body, SocialLoginBody.class);
+ ValidatorUtils.validate(loginBody);
+ AuthResponse response = SocialUtils.loginAuth(
+ loginBody.getSource(), loginBody.getSocialCode(),
+ loginBody.getSocialState(), socialProperties);
+ if (!response.ok()) {
+ throw new ServiceException(response.getMsg());
+ }
+ AuthUser authUserData = response.getData();
+
+ List list = sysSocialService.selectListByAuthId(authUserData.getSource() + authUserData.getUuid());
+ if (CollUtil.isEmpty(list)) {
+ throw new ServiceException("你还没有绑定第三方账号,绑定后才可以登录!");
+ }
+ Optional opt = list.stream().filter(x -> x.getTenantId().equals(loginBody.getTenantId())).findAny();
+ if (opt.isEmpty()) {
+ throw new ServiceException("对不起,你没有权限登录当前租户!");
+ }
+ SysSocialVo social = opt.get();
+
+ // 查找用户
+ SysUserVo user = loadUser(social.getTenantId(), social.getUserId());
+
+ // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
+ LoginUser loginUser = loginService.buildLoginUser(user);
+ loginUser.setClientKey(client.getClientKey());
+ loginUser.setDeviceType(client.getDeviceType());
+ SaLoginModel model = new SaLoginModel();
+ model.setDevice(client.getDeviceType());
+ // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
+ // 例如: 后台用户30分钟过期 app用户1天过期
+ model.setTimeout(client.getTimeout());
+ model.setActiveTimeout(client.getActiveTimeout());
+ model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
+ // 生成token
+ LoginHelper.login(loginUser, model);
+
+ LoginVo loginVo = new LoginVo();
+ loginVo.setAccessToken(StpUtil.getTokenValue());
+ loginVo.setExpireIn(StpUtil.getTokenTimeout());
+ loginVo.setClientId(client.getClientId());
+ return loginVo;
+ }
+
+ private SysUserVo loadUser(Long tenantId, Long userId) {
+ SysUserVo user = userService.selectTenantUserById(tenantId, userId);
+ if (ObjectUtil.isNull(user)) {
+ log.info("登录用户:{} 不存在.", "");
+ throw new UserException("user.not.exists", "");
+ } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
+ log.info("登录用户:{} 已被停用.", "");
+ throw new UserException("user.blocked", "");
+ }
+ return user;
+ }
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/XcxAuthStrategy.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/XcxAuthStrategy.java
new file mode 100644
index 0000000..cd702bb
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/XcxAuthStrategy.java
@@ -0,0 +1,94 @@
+package com.ruoyi.web.service.impl;
+
+import cn.dev33.satoken.stp.SaLoginModel;
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.util.ObjectUtil;
+import jakarta.annotation.Resource;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import com.ruoyi.common.core.core.domain.model.XcxLoginBody;
+import com.ruoyi.common.core.core.domain.model.XcxLoginUser;
+import com.ruoyi.common.core.enums.UserStatus;
+import com.ruoyi.common.core.utils.ValidatorUtils;
+import com.ruoyi.common.json.utils.JsonUtils;
+import com.ruoyi.common.security.utils.LoginHelper;
+import com.ruoyi.system.domain.SysClient;
+import com.ruoyi.system.domain.vo.SysClientVo;
+import com.ruoyi.system.domain.vo.SysUserVo;
+import com.ruoyi.web.domain.vo.LoginVo;
+import com.ruoyi.web.service.IAuthStrategy;
+import com.ruoyi.web.service.SysLoginService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 小程序认证策略
+ *
+ * @author Michelle.Chung
+ */
+@Slf4j
+@Service("xcx" + IAuthStrategy.BASE_NAME)
+@RequiredArgsConstructor
+public class XcxAuthStrategy implements IAuthStrategy {
+
+ @Resource
+ private SysLoginService loginService;
+
+ @Override
+ public LoginVo login(String body, SysClientVo client) {
+ XcxLoginBody loginBody = JsonUtils.parseObject(body, XcxLoginBody.class);
+ ValidatorUtils.validate(loginBody);
+ // xcxCode 为 小程序调用 wx.login 授权后获取
+ String xcxCode = loginBody.getXcxCode();
+ // 多个小程序识别使用
+ String appid = loginBody.getAppid();
+
+ // todo 以下自行实现
+ // 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid
+ String openid = "";
+ // 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可
+ SysUserVo user = loadUserByOpenid(openid);
+
+ // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
+ XcxLoginUser loginUser = new XcxLoginUser();
+ loginUser.setTenantId(user.getTenantId());
+ loginUser.setUserId(user.getUserId());
+ loginUser.setUsername(user.getUserName());
+ loginUser.setNickname(user.getNickName());
+ loginUser.setUserType(user.getUserType());
+ loginUser.setClientKey(client.getClientKey());
+ loginUser.setDeviceType(client.getDeviceType());
+ loginUser.setOpenid(openid);
+
+ SaLoginModel model = new SaLoginModel();
+ model.setDevice(client.getDeviceType());
+ // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
+ // 例如: 后台用户30分钟过期 app用户1天过期
+ model.setTimeout(client.getTimeout());
+ model.setActiveTimeout(client.getActiveTimeout());
+ model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId());
+ // 生成token
+ LoginHelper.login(loginUser, model);
+
+ LoginVo loginVo = new LoginVo();
+ loginVo.setAccessToken(StpUtil.getTokenValue());
+ loginVo.setExpireIn(StpUtil.getTokenTimeout());
+ loginVo.setClientId(client.getClientId());
+ loginVo.setOpenid(openid);
+ return loginVo;
+ }
+
+ private SysUserVo loadUserByOpenid(String openid) {
+ // 使用 openid 查询绑定用户 如未绑定用户 则根据业务自行处理 例如 创建默认用户
+ // todo 自行实现 userService.selectUserByOpenid(openid);
+ SysUserVo user = new SysUserVo();
+ if (ObjectUtil.isNull(user)) {
+ log.info("登录用户:{} 不存在.", openid);
+ // todo 用户不存在 业务逻辑自行实现
+ } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
+ log.info("登录用户:{} 已被停用.", openid);
+ // todo 用户已被停用 业务逻辑自行实现
+ }
+ return user;
+ }
+
+}
diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
index 99f9e7b..50274c6 100644
--- a/ruoyi-admin/src/main/resources/application-dev.yml
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -157,3 +157,79 @@ sms:
access-key-secret: 您的accessKeySecret
signature: 您的短信签名
sdk-app-id: 您的sdkAppId
+
+--- # 三方授权
+justauth:
+ # 前端外网访问地址
+ address: http://localhost:80
+ type:
+ maxkey:
+ # maxkey 服务器地址
+ # 注意 如下均配置均不需要修改 maxkey 已经内置好了数据
+ server-url: http://sso.maxkey.top
+ client-id: 876892492581044224
+ client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8
+ redirect-uri: ${justauth.address}/social-callback?source=maxkey
+ topiam:
+ # topiam 服务器地址
+ server-url: http://127.0.0.1:1989/api/v1/authorize/y0q************spq***********8ol
+ client-id: 449c4*********937************759
+ client-secret: ac7***********1e0************28d
+ redirect-uri: ${justauth.address}/social-callback?source=topiam
+ scopes: [openid, email, phone, profile]
+ qq:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=qq
+ union-id: false
+ weibo:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=weibo
+ gitee:
+ client-id: 91436b7940090**********d67eea73acbf61b6b590751a98
+ client-secret: 02c6fcfd70342980cd8**********c754d7a264c4e125f9ba915ac
+ redirect-uri: ${justauth.address}/social-callback?source=gitee
+ dingtalk:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=dingtalk
+ baidu:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=baidu
+ csdn:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=csdn
+ coding:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=coding
+ coding-group-name: xx
+ oschina:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=oschina
+ alipay_wallet:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet
+ alipay-public-key: MIIB**************DAQAB
+ wechat_open:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=wechat_open
+ wechat_mp:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=wechat_mp
+ wechat_enterprise:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise
+ agent-id: 1000002
+ gitlab:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=gitlab
diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml
index fc107f6..52edd47 100644
--- a/ruoyi-admin/src/main/resources/application-prod.yml
+++ b/ruoyi-admin/src/main/resources/application-prod.yml
@@ -171,3 +171,80 @@ sms:
access-key-secret: 您的accessKeySecret
signature: 您的短信签名
sdk-app-id: 您的sdkAppId
+
+
+--- # 三方授权
+justauth:
+ # 前端外网访问地址
+ address: http://localhost:80
+ type:
+ maxkey:
+ # maxkey 服务器地址
+ # 注意 如下均配置均不需要修改 maxkey 已经内置好了数据
+ server-url: http://sso.maxkey.top
+ client-id: 876892492581044224
+ client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8
+ redirect-uri: ${justauth.address}/social-callback?source=maxkey
+ topiam:
+ # topiam 服务器地址
+ server-url: http://127.0.0.1:1989/api/v1/authorize/y0q************spq***********8ol
+ client-id: 449c4*********937************759
+ client-secret: ac7***********1e0************28d
+ redirect-uri: ${justauth.address}/social-callback?source=topiam
+ scopes: [openid, email, phone, profile]
+ qq:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=qq
+ union-id: false
+ weibo:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=weibo
+ gitee:
+ client-id: 91436b7940090**********d67eea73acbf61b6b590751a98
+ client-secret: 02c6fcfd70342980cd8**********c754d7a264c4e125f9ba915ac
+ redirect-uri: ${justauth.address}/social-callback?source=gitee
+ dingtalk:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=dingtalk
+ baidu:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=baidu
+ csdn:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=csdn
+ coding:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=coding
+ coding-group-name: xx
+ oschina:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=oschina
+ alipay_wallet:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet
+ alipay-public-key: MIIB**************DAQAB
+ wechat_open:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=wechat_open
+ wechat_mp:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=wechat_mp
+ wechat_enterprise:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise
+ agent-id: 1000002
+ gitlab:
+ client-id: 10**********6
+ client-secret: 1f7d08**********5b7**********29e
+ redirect-uri: ${justauth.address}/social-callback?source=gitlab
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index f629313..ed263d7 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -25,6 +25,7 @@
ruoyi-common-redis
ruoyi-common-security
ruoyi-common-sms
+ ruoyi-common-social
ruoyi-common-springdoc
ruoyi-common-tenant
ruoyi-common-web
diff --git a/ruoyi-common/ruoyi-common-bom/pom.xml b/ruoyi-common/ruoyi-common-bom/pom.xml
index d128a24..411cbf3 100644
--- a/ruoyi-common/ruoyi-common-bom/pom.xml
+++ b/ruoyi-common/ruoyi-common-bom/pom.xml
@@ -108,8 +108,15 @@
com.ruoyi
ruoyi-common-sms
${revision}
-
+
+
+
+ com.ruoyi
+ ruoyi-common-social
+ ${revision}
+
+
com.ruoyi
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/SmsLoginBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/SmsLoginBody.java
new file mode 100644
index 0000000..6cb854d
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/SmsLoginBody.java
@@ -0,0 +1,29 @@
+package com.ruoyi.common.core.core.domain.model;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 短信登录对象
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class SmsLoginBody extends LoginBody {
+
+ /**
+ * 手机号
+ */
+ @NotBlank(message = "{user.phonenumber.not.blank}")
+ private String phonenumber;
+
+ /**
+ * 短信code
+ */
+ @NotBlank(message = "{sms.code.not.blank}")
+ private String smsCode;
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/SocialLoginBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/SocialLoginBody.java
new file mode 100644
index 0000000..5e85981
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/SocialLoginBody.java
@@ -0,0 +1,35 @@
+package com.ruoyi.common.core.core.domain.model;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 三方登录对象
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class SocialLoginBody extends LoginBody {
+
+ /**
+ * 第三方登录平台
+ */
+ @NotBlank(message = "{social.source.not.blank}")
+ private String source;
+
+ /**
+ * 第三方登录code
+ */
+ @NotBlank(message = "{social.code.not.blank}")
+ private String socialCode;
+
+ /**
+ * 第三方登录socialState
+ */
+ @NotBlank(message = "{social.state.not.blank}")
+ private String socialState;
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/XcxLoginBody.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/XcxLoginBody.java
new file mode 100644
index 0000000..793fac9
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/XcxLoginBody.java
@@ -0,0 +1,28 @@
+package com.ruoyi.common.core.core.domain.model;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 三方登录对象
+ *
+ * @author Lion Li
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class XcxLoginBody extends LoginBody {
+
+ /**
+ * 小程序id(多个小程序时使用)
+ */
+ private String appid;
+
+ /**
+ * 小程序code
+ */
+ @NotBlank(message = "{xcx.code.not.blank}")
+ private String xcxCode;
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/XcxLoginUser.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/XcxLoginUser.java
new file mode 100644
index 0000000..a180115
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/core/domain/model/XcxLoginUser.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.core.core.domain.model;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+
+/**
+ * 小程序登录用户身份权限
+ *
+ * @author Lion Li
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class XcxLoginUser extends LoginUser {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * openid
+ */
+ private String openid;
+
+}
diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityConfig.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityConfig.java
index 09b7b5f..73193c2 100644
--- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityConfig.java
+++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityConfig.java
@@ -49,7 +49,16 @@ public class SecurityConfig implements WebMvcConfigurer {
// 检查是否登录 是否有token
StpUtil.checkLogin();
- //TODO :以后完善多平台登录校验clientID功能
+ // 检查 header 与 param 里的 clientid 与 token 里的是否一致
+ String headerCid = ServletUtils.getRequest().getHeader(LoginHelper.CLIENT_KEY);
+ String paramCid = ServletUtils.getParameter(LoginHelper.CLIENT_KEY);
+ String clientId = StpUtil.getExtra(LoginHelper.CLIENT_KEY).toString();
+ if (!StringUtils.equalsAny(clientId, headerCid, paramCid)) {
+ // token 无效
+ throw NotLoginException.newInstance(StpUtil.getLoginType(),
+ "-100", "客户端ID与Token不匹配",
+ StpUtil.getTokenValue());
+ }
});
})).addPathPatterns("/**")
diff --git a/ruoyi-common/ruoyi-common-social/pom.xml b/ruoyi-common/ruoyi-common-social/pom.xml
new file mode 100644
index 0000000..7dfe2e8
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-social/pom.xml
@@ -0,0 +1,34 @@
+
+
+
+ com.ruoyi
+ ruoyi-common
+ ${revision}
+
+ 4.0.0
+
+ ruoyi-common-social
+
+
+ ruoyi-common-social 三方授权认证
+
+
+
+
+ me.zhyd.oauth
+ JustAuth
+
+
+
+ com.ruoyi
+ ruoyi-common-json
+
+
+
+ com.ruoyi
+ ruoyi-common-redis
+
+
+
diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/config/SocialAutoConfiguration.java b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/config/SocialAutoConfiguration.java
new file mode 100644
index 0000000..6a28866
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/config/SocialAutoConfiguration.java
@@ -0,0 +1,23 @@
+package com.ruoyi.common.social.config;
+
+import me.zhyd.oauth.cache.AuthStateCache;
+import com.ruoyi.common.social.config.properties.SocialProperties;
+import com.ruoyi.common.social.utils.AuthRedisStateCache;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * Social 配置属性
+ * @author thiszhc
+ */
+@AutoConfiguration
+@EnableConfigurationProperties(SocialProperties.class)
+public class SocialAutoConfiguration {
+
+ @Bean
+ public AuthStateCache authStateCache() {
+ return new AuthRedisStateCache();
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/config/properties/SocialLoginConfigProperties.java b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/config/properties/SocialLoginConfigProperties.java
new file mode 100644
index 0000000..2d83a73
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/config/properties/SocialLoginConfigProperties.java
@@ -0,0 +1,75 @@
+package com.ruoyi.common.social.config.properties;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 社交登录配置
+ *
+ * @author thiszhc
+ */
+@Data
+public class SocialLoginConfigProperties {
+
+ /**
+ * 应用 ID
+ */
+ private String clientId;
+
+ /**
+ * 应用密钥
+ */
+ private String clientSecret;
+
+ /**
+ * 回调地址
+ */
+ private String redirectUri;
+
+ /**
+ * 是否获取unionId
+ */
+ private boolean unionId;
+
+ /**
+ * Coding 企业名称
+ */
+ private String codingGroupName;
+
+ /**
+ * 支付宝公钥
+ */
+ private String alipayPublicKey;
+
+ /**
+ * 企业微信应用ID
+ */
+ private String agentId;
+
+ /**
+ * stackoverflow api key
+ */
+ private String stackOverflowKey;
+
+ /**
+ * 设备ID
+ */
+ private String deviceId;
+
+ /**
+ * 客户端系统类型
+ */
+ private String clientOsType;
+
+ /**
+ * maxkey 服务器地址
+ */
+ private String serverUrl;
+
+ /**
+ * 请求范围
+ */
+ private List scopes;
+
+}
diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/config/properties/SocialProperties.java b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/config/properties/SocialProperties.java
new file mode 100644
index 0000000..9a488e9
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/config/properties/SocialProperties.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.social.config.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * Social 配置属性
+ *
+ * @author thiszhc
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "justauth")
+public class SocialProperties {
+
+ /**
+ * 授权类型
+ */
+ private Map type;
+
+}
diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/maxkey/AuthMaxKeyRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/maxkey/AuthMaxKeyRequest.java
new file mode 100644
index 0000000..42cf563
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/maxkey/AuthMaxKeyRequest.java
@@ -0,0 +1,80 @@
+package com.ruoyi.common.social.maxkey;
+
+import cn.hutool.core.lang.Dict;
+import me.zhyd.oauth.cache.AuthStateCache;
+import me.zhyd.oauth.config.AuthConfig;
+import me.zhyd.oauth.exception.AuthException;
+import me.zhyd.oauth.model.AuthCallback;
+import me.zhyd.oauth.model.AuthToken;
+import me.zhyd.oauth.model.AuthUser;
+import me.zhyd.oauth.request.AuthDefaultRequest;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.json.utils.JsonUtils;
+
+/**
+ * @author 长春叭哥 2023年03月26日
+ */
+public class AuthMaxKeyRequest extends AuthDefaultRequest {
+
+ public static final String SERVER_URL = SpringUtils.getProperty("justauth.type.maxkey.server-url");
+
+ /**
+ * 设定归属域
+ */
+ public AuthMaxKeyRequest(AuthConfig config) {
+ super(config, AuthMaxKeySource.MAXKEY);
+ }
+
+ public AuthMaxKeyRequest(AuthConfig config, AuthStateCache authStateCache) {
+ super(config, AuthMaxKeySource.MAXKEY, authStateCache);
+ }
+
+ @Override
+ protected AuthToken getAccessToken(AuthCallback authCallback) {
+ String body = doPostAuthorizationCode(authCallback.getCode());
+ Dict object = JsonUtils.parseMap(body);
+ // oauth/token 验证异常
+ if (object.containsKey("error")) {
+ throw new AuthException(object.getStr("error_description"));
+ }
+ // user 验证异常
+ if (object.containsKey("message")) {
+ throw new AuthException(object.getStr("message"));
+ }
+ return AuthToken.builder()
+ .accessToken(object.getStr("access_token"))
+ .refreshToken(object.getStr("refresh_token"))
+ .idToken(object.getStr("id_token"))
+ .tokenType(object.getStr("token_type"))
+ .scope(object.getStr("scope"))
+ .build();
+ }
+
+ @Override
+ protected AuthUser getUserInfo(AuthToken authToken) {
+ String body = doGetUserInfo(authToken);
+ Dict object = JsonUtils.parseMap(body);
+ // oauth/token 验证异常
+ if (object.containsKey("error")) {
+ throw new AuthException(object.getStr("error_description"));
+ }
+ // user 验证异常
+ if (object.containsKey("message")) {
+ throw new AuthException(object.getStr("message"));
+ }
+ return AuthUser.builder()
+ .uuid(object.getStr("userId"))
+ .username(object.getStr("username"))
+ .nickname(object.getStr("displayName"))
+ .avatar(object.getStr("avatar_url"))
+ .blog(object.getStr("web_url"))
+ .company(object.getStr("organization"))
+ .location(object.getStr("location"))
+ .email(object.getStr("email"))
+ .remark(object.getStr("bio"))
+ .token(authToken)
+ .source(source.toString())
+ .build();
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/maxkey/AuthMaxKeySource.java b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/maxkey/AuthMaxKeySource.java
new file mode 100644
index 0000000..3928332
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/maxkey/AuthMaxKeySource.java
@@ -0,0 +1,52 @@
+package com.ruoyi.common.social.maxkey;
+
+import me.zhyd.oauth.config.AuthSource;
+import me.zhyd.oauth.request.AuthDefaultRequest;
+
+/**
+ * Oauth2 默认接口说明
+ *
+ * @author 长春叭哥 2023年03月26日
+ *
+ */
+public enum AuthMaxKeySource implements AuthSource {
+
+ /**
+ * 自己搭建的 maxkey 私服
+ */
+ MAXKEY {
+
+ /**
+ * 授权的api
+ */
+ @Override
+ public String authorize() {
+ return AuthMaxKeyRequest.SERVER_URL + "/sign/authz/oauth/v20/authorize";
+ }
+
+ /**
+ * 获取accessToken的api
+ */
+ @Override
+ public String accessToken() {
+ return AuthMaxKeyRequest.SERVER_URL + "/sign/authz/oauth/v20/token";
+ }
+
+ /**
+ * 获取用户信息的api
+ */
+ @Override
+ public String userInfo() {
+ return AuthMaxKeyRequest.SERVER_URL + "/sign/api/oauth/v20/me";
+ }
+
+ /**
+ * 平台对应的 AuthRequest 实现类,必须继承自 {@link AuthDefaultRequest}
+ */
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthMaxKeyRequest.class;
+ }
+
+ }
+}
diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/topiam/AuthTopIamRequest.java b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/topiam/AuthTopIamRequest.java
new file mode 100644
index 0000000..5d1d368
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/topiam/AuthTopIamRequest.java
@@ -0,0 +1,100 @@
+package com.ruoyi.common.social.topiam;
+
+import cn.hutool.core.lang.Dict;
+import cn.hutool.core.util.StrUtil;
+import com.xkcoding.http.support.HttpHeader;
+import lombok.extern.slf4j.Slf4j;
+import me.zhyd.oauth.cache.AuthStateCache;
+import me.zhyd.oauth.config.AuthConfig;
+import me.zhyd.oauth.exception.AuthException;
+import me.zhyd.oauth.model.AuthCallback;
+import me.zhyd.oauth.model.AuthToken;
+import me.zhyd.oauth.model.AuthUser;
+import me.zhyd.oauth.request.AuthDefaultRequest;
+import me.zhyd.oauth.utils.HttpUtils;
+import me.zhyd.oauth.utils.UrlBuilder;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.json.utils.JsonUtils;
+
+import static com.ruoyi.common.social.topiam.AuthTopiamSource.TOPIAM;
+
+/**
+ * TopIAM 认证请求
+ *
+ * @author xlsea
+ * @since 2024-01-06
+ */
+@Slf4j
+public class AuthTopIamRequest extends AuthDefaultRequest {
+
+ public static final String SERVER_URL = SpringUtils.getProperty("justauth.type.topiam.server-url");
+
+ /**
+ * 设定归属域
+ */
+ public AuthTopIamRequest(AuthConfig config) {
+ super(config, TOPIAM);
+ }
+
+ public AuthTopIamRequest(AuthConfig config, AuthStateCache authStateCache) {
+ super(config, TOPIAM, authStateCache);
+ }
+
+ @Override
+ protected AuthToken getAccessToken(AuthCallback authCallback) {
+ String body = doPostAuthorizationCode(authCallback.getCode());
+ Dict object = JsonUtils.parseMap(body);
+ checkResponse(object);
+ return AuthToken.builder()
+ .accessToken(object.getStr("access_token"))
+ .refreshToken(object.getStr("refresh_token"))
+ .idToken(object.getStr("id_token"))
+ .tokenType(object.getStr("token_type"))
+ .scope(object.getStr("scope"))
+ .build();
+ }
+
+ @Override
+ protected AuthUser getUserInfo(AuthToken authToken) {
+ String body = doGetUserInfo(authToken);
+ Dict object = JsonUtils.parseMap(body);
+ checkResponse(object);
+ return AuthUser.builder()
+ .uuid(object.getStr("sub"))
+ .username(object.getStr("preferred_username"))
+ .nickname(object.getStr("nickname"))
+ .avatar(object.getStr("picture"))
+ .email(object.getStr("email"))
+ .token(authToken)
+ .source(source.toString())
+ .build();
+ }
+
+
+ @Override
+ protected String doGetUserInfo(AuthToken authToken) {
+ return new HttpUtils(config.getHttpConfig()).get(source.userInfo(), null, new HttpHeader()
+ .add("Content-Type", "application/json")
+ .add("Authorization", "Bearer " + authToken.getAccessToken()), false).getBody();
+ }
+
+
+ @Override
+ public String authorize(String state) {
+ return UrlBuilder.fromBaseUrl(super.authorize(state))
+ .queryParam("scope", StrUtil.join("%20", config.getScopes()))
+ .build();
+ }
+
+ public static void checkResponse(Dict object) {
+ // oauth/token 验证异常
+ if (object.containsKey("error")) {
+ throw new AuthException(object.getStr("error_description"));
+ }
+ // user 验证异常
+ if (object.containsKey("message")) {
+ throw new AuthException(object.getStr("message"));
+ }
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/topiam/AuthTopiamSource.java b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/topiam/AuthTopiamSource.java
new file mode 100644
index 0000000..5bf5a48
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/topiam/AuthTopiamSource.java
@@ -0,0 +1,51 @@
+package com.ruoyi.common.social.topiam;
+
+import me.zhyd.oauth.config.AuthSource;
+import me.zhyd.oauth.request.AuthDefaultRequest;
+
+/**
+ * Oauth2 默认接口说明
+ *
+ * @author xlsea
+ * @since 2024-01-06
+ */
+public enum AuthTopiamSource implements AuthSource {
+
+ /**
+ * 测试
+ */
+ TOPIAM {
+ /**
+ * 授权的api
+ */
+ @Override
+ public String authorize() {
+ return AuthTopIamRequest.SERVER_URL + "/oauth2/auth";
+ }
+
+ /**
+ * 获取accessToken的api
+ */
+ @Override
+ public String accessToken() {
+ return AuthTopIamRequest.SERVER_URL + "/oauth2/token";
+ }
+
+ /**
+ * 获取用户信息的api
+ */
+ @Override
+ public String userInfo() {
+ return AuthTopIamRequest.SERVER_URL + "/oauth2/userinfo";
+ }
+
+ /**
+ * 平台对应的 AuthRequest 实现类,必须继承自 {@link AuthDefaultRequest}
+ */
+ @Override
+ public Class extends AuthDefaultRequest> getTargetClass() {
+ return AuthTopIamRequest.class;
+ }
+
+ }
+}
diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/utils/AuthRedisStateCache.java b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/utils/AuthRedisStateCache.java
new file mode 100644
index 0000000..e8c6aa5
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/utils/AuthRedisStateCache.java
@@ -0,0 +1,61 @@
+package com.ruoyi.common.social.utils;
+
+import lombok.AllArgsConstructor;
+import me.zhyd.oauth.cache.AuthStateCache;
+import com.ruoyi.common.core.constant.GlobalConstants;
+import com.ruoyi.common.redis.utils.RedisUtils;
+
+import java.time.Duration;
+
+/**
+ * 授权状态缓存
+ */
+@AllArgsConstructor
+public class AuthRedisStateCache implements AuthStateCache {
+
+ /**
+ * 存入缓存
+ *
+ * @param key 缓存key
+ * @param value 缓存内容
+ */
+ @Override
+ public void cache(String key, String value) {
+ // 授权超时时间 默认三分钟
+ RedisUtils.setCacheObject(GlobalConstants.SOCIAL_AUTH_CODE_KEY + key, value, Duration.ofMinutes(3));
+ }
+
+ /**
+ * 存入缓存
+ *
+ * @param key 缓存key
+ * @param value 缓存内容
+ * @param timeout 指定缓存过期时间(毫秒)
+ */
+ @Override
+ public void cache(String key, String value, long timeout) {
+ RedisUtils.setCacheObject(GlobalConstants.SOCIAL_AUTH_CODE_KEY + key, value, Duration.ofMillis(timeout));
+ }
+
+ /**
+ * 获取缓存内容
+ *
+ * @param key 缓存key
+ * @return 缓存内容
+ */
+ @Override
+ public String get(String key) {
+ return RedisUtils.getCacheObject(GlobalConstants.SOCIAL_AUTH_CODE_KEY + key);
+ }
+
+ /**
+ * 是否存在key,如果对应key的value值已过期,也返回false
+ *
+ * @param key 缓存key
+ * @return true:存在key,并且value没过期;false:key不存在或者已过期
+ */
+ @Override
+ public boolean containsKey(String key) {
+ return RedisUtils.hasKey(GlobalConstants.SOCIAL_AUTH_CODE_KEY + key);
+ }
+}
diff --git a/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/utils/SocialUtils.java b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/utils/SocialUtils.java
new file mode 100644
index 0000000..2b9b395
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-social/src/main/java/com/ruoyi/common/social/utils/SocialUtils.java
@@ -0,0 +1,73 @@
+package com.ruoyi.common.social.utils;
+
+import cn.hutool.core.util.ObjectUtil;
+import me.zhyd.oauth.config.AuthConfig;
+import me.zhyd.oauth.exception.AuthException;
+import me.zhyd.oauth.model.AuthCallback;
+import me.zhyd.oauth.model.AuthResponse;
+import me.zhyd.oauth.model.AuthUser;
+import me.zhyd.oauth.request.*;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.social.config.properties.SocialLoginConfigProperties;
+import com.ruoyi.common.social.config.properties.SocialProperties;
+import com.ruoyi.common.social.maxkey.AuthMaxKeyRequest;
+import com.ruoyi.common.social.topiam.AuthTopIamRequest;
+
+/**
+ * 认证授权工具类
+ *
+ * @author thiszhc
+ */
+public class SocialUtils {
+
+ private static final AuthRedisStateCache STATE_CACHE = SpringUtils.getBean(AuthRedisStateCache.class);
+
+ @SuppressWarnings("unchecked")
+ public static AuthResponse loginAuth(String source, String code, String state, SocialProperties socialProperties) throws AuthException {
+ AuthRequest authRequest = getAuthRequest(source, socialProperties);
+ AuthCallback callback = new AuthCallback();
+ callback.setCode(code);
+ callback.setState(state);
+ return authRequest.login(callback);
+ }
+
+ public static AuthRequest getAuthRequest(String source, SocialProperties socialProperties) throws AuthException {
+ SocialLoginConfigProperties obj = socialProperties.getType().get(source);
+ if (ObjectUtil.isNull(obj)) {
+ throw new AuthException("不支持的第三方登录类型");
+ }
+ AuthConfig.AuthConfigBuilder builder = AuthConfig.builder()
+ .clientId(obj.getClientId())
+ .clientSecret(obj.getClientSecret())
+ .redirectUri(obj.getRedirectUri())
+ .scopes(obj.getScopes());
+ return switch (source.toLowerCase()) {
+ case "dingtalk" -> new AuthDingTalkRequest(builder.build(), STATE_CACHE);
+ case "baidu" -> new AuthBaiduRequest(builder.build(), STATE_CACHE);
+ case "github" -> new AuthGithubRequest(builder.build(), STATE_CACHE);
+ case "gitee" -> new AuthGiteeRequest(builder.build(), STATE_CACHE);
+ case "weibo" -> new AuthWeiboRequest(builder.build(), STATE_CACHE);
+ case "coding" -> new AuthCodingRequest(builder.build(), STATE_CACHE);
+ case "oschina" -> new AuthOschinaRequest(builder.build(), STATE_CACHE);
+ // 支付宝在创建回调地址时,不允许使用localhost或者127.0.0.1,所以这儿的回调地址使用的局域网内的ip
+ case "alipay_wallet" -> new AuthAlipayRequest(builder.build(), socialProperties.getType().get("alipay_wallet").getAlipayPublicKey(), STATE_CACHE);
+ case "qq" -> new AuthQqRequest(builder.build(), STATE_CACHE);
+ case "wechat_open" -> new AuthWeChatOpenRequest(builder.build(), STATE_CACHE);
+ case "taobao" -> new AuthTaobaoRequest(builder.build(), STATE_CACHE);
+ case "douyin" -> new AuthDouyinRequest(builder.build(), STATE_CACHE);
+ case "linkedin" -> new AuthLinkedinRequest(builder.build(), STATE_CACHE);
+ case "microsoft" -> new AuthMicrosoftRequest(builder.build(), STATE_CACHE);
+ case "renren" -> new AuthRenrenRequest(builder.build(), STATE_CACHE);
+ case "stack_overflow" -> new AuthStackOverflowRequest(builder.stackOverflowKey("").build(), STATE_CACHE);
+ case "huawei" -> new AuthHuaweiRequest(builder.build(), STATE_CACHE);
+ case "wechat_enterprise" -> new AuthWeChatEnterpriseQrcodeRequest(builder.agentId("").build(), STATE_CACHE);
+ case "gitlab" -> new AuthGitlabRequest(builder.build(), STATE_CACHE);
+ case "wechat_mp" -> new AuthWeChatMpRequest(builder.build(), STATE_CACHE);
+ case "aliyun" -> new AuthAliyunRequest(builder.build(), STATE_CACHE);
+ case "maxkey" -> new AuthMaxKeyRequest(builder.build(), STATE_CACHE);
+ case "topiam" -> new AuthTopIamRequest(builder.build(), STATE_CACHE);
+ default -> throw new AuthException("未获取到有效的Auth配置");
+ };
+ }
+}
+
diff --git a/ruoyi-common/ruoyi-common-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..fb6d9fa
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.ruoyi.common.social.config.SocialAutoConfiguration
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysSocialController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysSocialController.java
new file mode 100644
index 0000000..8ba2e6f
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysSocialController.java
@@ -0,0 +1,40 @@
+package com.ruoyi.system.controller.system;
+
+import jakarta.annotation.Resource;
+import lombok.RequiredArgsConstructor;
+import com.ruoyi.common.core.core.domain.R;
+import com.ruoyi.common.security.utils.LoginHelper;
+import com.ruoyi.common.web.core.BaseController;
+import com.ruoyi.system.domain.vo.SysSocialVo;
+import com.ruoyi.system.service.ISysSocialService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 社会化关系
+ *
+ * @author thiszhc
+ * @date 2023-06-16
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/system/social")
+public class SysSocialController extends BaseController {
+
+ @Resource
+ private ISysSocialService sysSocialService;
+
+ /**
+ * 查询社会化关系列表
+ */
+ @GetMapping("/list")
+ public R> list() {
+ return R.ok(sysSocialService.selectListByUserId(LoginHelper.getUserId()));
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysSocial.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysSocial.java
new file mode 100644
index 0000000..3291a28
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysSocial.java
@@ -0,0 +1,139 @@
+package com.ruoyi.system.domain;
+
+import com.mybatisflex.annotation.Id;
+import com.mybatisflex.annotation.Table;
+import com.ruoyi.common.orm.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 社会化关系对象 sys_social
+ *
+ * @author thiszhc
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Table("sys_social")
+public class SysSocial extends BaseEntity {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键
+ */
+ @Id
+ private Long socialId;
+
+ /**
+ * 用户ID
+ */
+ private Long userId;
+
+ /**
+ * 的唯一ID
+ */
+ private String authId;
+
+ /**
+ * 用户来源
+ */
+ private String source;
+
+ /**
+ * 用户的授权令牌
+ */
+ private String accessToken;
+
+ /**
+ * 用户的授权令牌的有效期,部分平台可能没有
+ */
+ private int expireIn;
+
+ /**
+ * 刷新令牌,部分平台可能没有
+ */
+ private String refreshToken;
+
+ /**
+ * 用户的 open id
+ */
+ private String openId;
+
+ /**
+ * 授权的第三方账号
+ */
+ private String userName;
+
+ /**
+ * 授权的第三方昵称
+ */
+ private String nickName;
+
+ /**
+ * 授权的第三方邮箱
+ */
+ private String email;
+
+ /**
+ * 授权的第三方头像地址
+ */
+ private String avatar;
+
+ /**
+ * 平台的授权信息,部分平台可能没有
+ */
+ private String accessCode;
+
+ /**
+ * 用户的 unionid
+ */
+ private String unionId;
+
+ /**
+ * 授予的权限,部分平台可能没有
+ */
+ private String scope;
+
+ /**
+ * 个别平台的授权信息,部分平台可能没有
+ */
+ private String tokenType;
+
+ /**
+ * id token,部分平台可能没有
+ */
+ private String idToken;
+
+ /**
+ * 小米平台用户的附带属性,部分平台可能没有
+ */
+ private String macAlgorithm;
+
+ /**
+ * 小米平台用户的附带属性,部分平台可能没有
+ */
+ private String macKey;
+
+ /**
+ * 用户的授权code,部分平台可能没有
+ */
+ private String code;
+
+ /**
+ * Twitter平台用户的附带属性,部分平台可能没有
+ */
+ private String oauthToken;
+
+ /**
+ * Twitter平台用户的附带属性,部分平台可能没有
+ */
+ private String oauthTokenSecret;
+
+ /**
+ * 删除标志(0就代表存在 1就代表删除)
+ */
+ private Integer delFlag;
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysSocialBo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysSocialBo.java
new file mode 100644
index 0000000..cfb9cbc
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysSocialBo.java
@@ -0,0 +1,142 @@
+package com.ruoyi.system.domain.bo;
+
+import com.ruoyi.common.orm.core.domain.BaseEntity;
+import io.github.linpeilie.annotations.AutoMapper;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import com.ruoyi.system.domain.SysSocial;
+
+/**
+ * 社会化关系业务对象 sys_social
+ *
+ * @author Lion Li
+ */
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = SysSocial.class, reverseConvertGenerate = false)
+public class SysSocialBo extends BaseEntity {
+
+ /**
+ * 主键
+ */
+ @NotNull(message = "主键不能为空")
+ private Long socialId;
+
+ /**
+ * 的唯一ID
+ */
+ @NotBlank(message = "的唯一ID不能为空")
+ private String authId;
+
+ /**
+ * 用户来源
+ */
+ @NotBlank(message = "用户来源不能为空")
+ private String source;
+
+ /**
+ * 用户的授权令牌
+ */
+ @NotBlank(message = "用户的授权令牌不能为空")
+ private String accessToken;
+
+ /**
+ * 用户的授权令牌的有效期,部分平台可能没有
+ */
+ private int expireIn;
+
+ /**
+ * 刷新令牌,部分平台可能没有
+ */
+ private String refreshToken;
+
+ /**
+ * 平台唯一id
+ */
+ private String openId;
+
+ /**
+ * 用户的 ID
+ */
+ @NotBlank(message = "用户的 ID不能为空")
+ private Long userId;
+
+ /**
+ * 平台的授权信息,部分平台可能没有
+ */
+ private String accessCode;
+
+ /**
+ * 用户的 unionid
+ */
+ private String unionId;
+
+ /**
+ * 授予的权限,部分平台可能没有
+ */
+ private String scope;
+
+ /**
+ * 授权的第三方账号
+ */
+ private String userName;
+
+ /**
+ * 授权的第三方昵称
+ */
+ private String nickName;
+
+ /**
+ * 授权的第三方邮箱
+ */
+ private String email;
+
+ /**
+ * 授权的第三方头像地址
+ */
+ private String avatar;
+
+ /**
+ * 个别平台的授权信息,部分平台可能没有
+ */
+ private String tokenType;
+
+ /**
+ * id token,部分平台可能没有
+ */
+ private String idToken;
+
+ /**
+ * 小米平台用户的附带属性,部分平台可能没有
+ */
+ private String macAlgorithm;
+
+ /**
+ * 小米平台用户的附带属性,部分平台可能没有
+ */
+ private String macKey;
+
+ /**
+ * 用户的授权code,部分平台可能没有
+ */
+ private String code;
+
+ /**
+ * Twitter平台用户的附带属性,部分平台可能没有
+ */
+ private String oauthToken;
+
+ /**
+ * Twitter平台用户的附带属性,部分平台可能没有
+ */
+ private String oauthTokenSecret;
+
+ /**
+ * 删除标志(0就代表存在 1就代表删除)
+ */
+ private Integer delFlag;
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysSocialVo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysSocialVo.java
new file mode 100644
index 0000000..6dacfbe
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysSocialVo.java
@@ -0,0 +1,140 @@
+package com.ruoyi.system.domain.vo;
+
+import com.ruoyi.common.orm.core.domain.BaseEntity;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import com.ruoyi.system.domain.SysSocial;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 社会化关系视图对象 sys_social
+ *
+ * @author thiszhc
+ */
+@Data
+@AutoMapper(target = SysSocial.class)
+public class SysSocialVo extends BaseEntity implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 主键
+ */
+ private Long socialId;
+
+ /**
+ * 用户ID
+ */
+ private Long userId;
+
+ /**
+ * 的唯一ID
+ */
+ private String authId;
+
+ /**
+ * 用户来源
+ */
+ private String source;
+
+ /**
+ * 用户的授权令牌
+ */
+ private String accessToken;
+
+ /**
+ * 用户的授权令牌的有效期,部分平台可能没有
+ */
+ private int expireIn;
+
+ /**
+ * 刷新令牌,部分平台可能没有
+ */
+ private String refreshToken;
+
+ /**
+ * 用户的 open id
+ */
+ private String openId;
+
+ /**
+ * 授权的第三方账号
+ */
+ private String userName;
+
+ /**
+ * 授权的第三方昵称
+ */
+ private String nickName;
+
+ /**
+ * 授权的第三方邮箱
+ */
+ private String email;
+
+ /**
+ * 授权的第三方头像地址
+ */
+ private String avatar;
+
+
+ /**
+ * 平台的授权信息,部分平台可能没有
+ */
+ private String accessCode;
+
+ /**
+ * 用户的 unionid
+ */
+ private String unionId;
+
+ /**
+ * 授予的权限,部分平台可能没有
+ */
+ private String scope;
+
+ /**
+ * 个别平台的授权信息,部分平台可能没有
+ */
+ private String tokenType;
+
+ /**
+ * id token,部分平台可能没有
+ */
+ private String idToken;
+
+ /**
+ * 小米平台用户的附带属性,部分平台可能没有
+ */
+ private String macAlgorithm;
+
+ /**
+ * 小米平台用户的附带属性,部分平台可能没有
+ */
+ private String macKey;
+
+ /**
+ * 用户的授权code,部分平台可能没有
+ */
+ private String code;
+
+ /**
+ * Twitter平台用户的附带属性,部分平台可能没有
+ */
+ private String oauthToken;
+
+ /**
+ * Twitter平台用户的附带属性,部分平台可能没有
+ */
+ private String oauthTokenSecret;
+
+ /**
+ * 删除标志(0就代表存在 1就代表删除)
+ */
+ private Integer delFlag;
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysSocialMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysSocialMapper.java
new file mode 100644
index 0000000..6289d36
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysSocialMapper.java
@@ -0,0 +1,15 @@
+package com.ruoyi.system.mapper;
+
+import com.mybatisflex.core.BaseMapper;
+import com.ruoyi.system.domain.SysSocial;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 社会化关系Mapper接口
+ *
+ * @author thiszhc
+ */
+@Mapper
+public interface SysSocialMapper extends BaseMapper {
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
index ebfc201..08e1511 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
@@ -39,6 +39,14 @@ public interface ISysConfigService extends IBaseService
*/
boolean selectCaptchaEnabled();
+ /**
+ * 获取注册开关(不走Mybatis-Flex租户插件)
+ *
+ * @param tenantId 租户id
+ * @return true开启,false关闭
+ */
+ boolean selectRegisterEnabled(Long tenantId);
+
/**
* 查询参数配置列表
*
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysSocialService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysSocialService.java
new file mode 100644
index 0000000..3011268
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysSocialService.java
@@ -0,0 +1,57 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.common.orm.core.service.IBaseService;
+import com.ruoyi.system.domain.SysSocial;
+import com.ruoyi.system.domain.bo.SysSocialBo;
+import com.ruoyi.system.domain.vo.SysSocialVo;
+
+import java.util.List;
+
+/**
+ * 社会化关系Service接口
+ *
+ * @author thiszhc
+ */
+public interface ISysSocialService extends IBaseService {
+
+
+ /**
+ * 查询社会化关系
+ */
+ SysSocialVo queryById(Long socialId);
+
+ /**
+ * 查询社会化关系列表
+ */
+ List queryList();
+
+ /**
+ * 查询社会化关系列表
+ */
+ List selectListByUserId(Long userId);
+
+ /**
+ * 新增授权关系
+ */
+ Boolean insertByBo(SysSocialBo bo);
+
+ /**
+ * 更新社会化关系
+ */
+ Boolean updateByBo(SysSocialBo bo);
+
+ /**
+ * 删除社会化关系信息
+ */
+ Boolean deleteWithValidById(Long id);
+
+
+ /**
+ * 根据 authId 查询 SysSocial 表和 SysUser 表,返回 SysSocialAuthResult 映射的对象
+ * @param authId 认证ID
+ * @return SysSocial
+ */
+ List selectListByAuthId(String authId);
+
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
index d17e049..44bdd1b 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
@@ -13,8 +13,7 @@ import java.util.List;
*
* @author ruoyi
*/
-public interface ISysUserService extends IBaseService
-{
+public interface ISysUserService extends IBaseService {
/**
* 根据条件分页查询用户列表
*
@@ -56,21 +55,39 @@ public interface ISysUserService extends IBaseService
SysUserVo selectUserByUserName(String userName);
/**
- * 登录时通过用户名、租户编号查询用户(不走Mybatis-Flex租户插件)
+ * 登录时通过租户编号、用户名查询用户(不走Mybatis-Flex租户插件)
*
* @param userName 用户名
* @param tenantId 租户编号
* @return 用户对象信息
*/
- SysUserVo selectTenantUserByUserName(String userName,Long tenantId);
+ SysUserVo selectTenantUserByUserName(Long tenantId, String userName);
/**
- * 通过邮箱查询用户
+ * 登录时通过租户编号、用户名查询用户(不走Mybatis-Flex租户插件)
+ *
+ * @param phonenumber 手机号
+ * @param tenantId 租户编号
+ * @return 用户对象信息
+ */
+ SysUserVo selectTenantUserByPhonenumber(Long tenantId, String phonenumber);
+
+ /**
+ * 登录时通过租户编号、邮箱查询用户(不走Mybatis-Flex租户插件)
*
* @param email 邮箱
* @return 用户对象信息
*/
- SysUserVo selectUserByEmail(String email);
+ SysUserVo selectTenantUserByEmail(Long tenantId, String email);
+
+ /**
+ * 登录时通过租户编号、用户id查询用户(不走Mybatis-Flex租户插件)
+ *
+ * @param tenantId 租户编号
+ * @param userId 用户id
+ * @return 用户对象信息
+ */
+ SysUserVo selectTenantUserById(Long tenantId, Long userId);
/**
* 通过用户ID查询用户
@@ -178,7 +195,7 @@ public interface ISysUserService extends IBaseService
/**
* 用户授权角色
*
- * @param userId 用户ID
+ * @param userId 用户ID
* @param roleIds 角色组
*/
void insertUserAuth(Long userId, Long[] roleIds);
@@ -227,9 +244,9 @@ public interface ISysUserService extends IBaseService
/**
* 导入用户数据
*
- * @param userList 用户数据列表
+ * @param userList 用户数据列表
* @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
- * @param operID 操作用户ID
+ * @param operID 操作用户ID
* @return 结果
*/
String importUser(List userList, Boolean isUpdateSupport, Long operID);
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
index 22bcb69..0ed7976 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
@@ -2,6 +2,7 @@ package com.ruoyi.system.service.impl;
import java.util.List;
+import cn.hutool.core.util.ObjectUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.ruoyi.common.core.constant.CacheNames;
@@ -12,6 +13,7 @@ import com.ruoyi.common.orm.core.page.PageQuery;
import com.ruoyi.common.orm.core.page.TableDataInfo;
import com.ruoyi.common.orm.core.service.impl.BaseServiceImpl;
import com.ruoyi.common.redis.utils.CacheUtils;
+import com.ruoyi.common.tenant.helper.TenantHelper;
import com.ruoyi.system.domain.bo.SysConfigBo;
import com.ruoyi.system.domain.vo.SysConfigVo;
import jakarta.annotation.Resource;
@@ -84,6 +86,26 @@ public class SysConfigServiceImpl extends BaseServiceImpl {
+ QueryWrapper queryWrapper = query()
+ .where(SYS_CONFIG.TENANT_ID.eq(tenantId))
+ .and(SYS_CONFIG.CONFIG_KEY.eq("sys.account.registerUser"));
+ SysConfig config = this.getOne(queryWrapper);
+ if (ObjectUtil.isNull(config)) {
+ return false;
+ }
+ return Convert.toBool(config.getConfigValue());
+ });
+ }
+
/**
* 构造查询条件
*
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
index db13524..58e22f1 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
@@ -20,6 +20,7 @@ import com.ruoyi.common.orm.core.page.PageQuery;
import com.ruoyi.common.orm.core.page.TableDataInfo;
import com.ruoyi.common.orm.core.service.impl.BaseServiceImpl;
import com.ruoyi.common.security.utils.LoginHelper;
+import com.ruoyi.common.tenant.helper.TenantHelper;
import com.ruoyi.system.domain.SysClient;
import com.ruoyi.system.domain.bo.SysLogininforBo;
import com.ruoyi.system.domain.vo.SysLogininforVo;
@@ -109,7 +110,7 @@ public class SysLogininforServiceImpl extends BaseServiceImpl insertLogininfor(logininfor));//支持注册时的动态多租户
}
private String getBlock(Object msg) {
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysSocialServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysSocialServiceImpl.java
new file mode 100644
index 0000000..61ec6c3
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysSocialServiceImpl.java
@@ -0,0 +1,103 @@
+package com.ruoyi.system.service.impl;
+
+import com.mybatisflex.core.query.QueryWrapper;
+import com.ruoyi.common.orm.core.service.impl.BaseServiceImpl;
+import jakarta.annotation.Resource;
+import lombok.RequiredArgsConstructor;
+import com.ruoyi.common.core.utils.MapstructUtils;
+import com.ruoyi.system.domain.SysSocial;
+import com.ruoyi.system.domain.bo.SysSocialBo;
+import com.ruoyi.system.domain.vo.SysSocialVo;
+import com.ruoyi.system.mapper.SysSocialMapper;
+import com.ruoyi.system.service.ISysSocialService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+import static com.ruoyi.system.domain.table.SysSocialTableDef.SYS_SOCIAL;
+
+/**
+ * 社会化关系Service业务层处理
+ *
+ * @author thiszhc
+ * @date 2023-06-12
+ */
+@RequiredArgsConstructor
+@Service
+public class SysSocialServiceImpl extends BaseServiceImpl implements ISysSocialService {
+
+ @Resource
+ private SysSocialMapper sysSocialMapper;
+
+
+ /**
+ * 查询社会化关系
+ */
+ @Override
+ public SysSocialVo queryById(Long socialId) {
+ return sysSocialMapper.selectOneWithRelationsByIdAs(socialId, SysSocialVo.class);
+ }
+
+ /**
+ * 授权列表
+ */
+ @Override
+ public List queryList() {
+ return sysSocialMapper.selectListByQueryAs(QueryWrapper.create().from(SYS_SOCIAL), SysSocialVo.class);
+ }
+
+ @Override
+ public List selectListByUserId(Long userId) {
+ return sysSocialMapper.selectListByQueryAs(QueryWrapper.create().from(SYS_SOCIAL).where(SYS_SOCIAL.USER_ID.eq(userId)), SysSocialVo.class);
+ }
+
+
+ /**
+ * 新增社会化关系
+ */
+ @Override
+ public Boolean insertByBo(SysSocialBo bo) {
+ SysSocial add = MapstructUtils.convert(bo, SysSocial.class);
+ validEntityBeforeSave(add);
+ return sysSocialMapper.insert(add, true) > 0;
+ }
+
+ /**
+ * 更新社会化关系
+ */
+ @Override
+ public Boolean updateByBo(SysSocialBo bo) {
+ SysSocial update = MapstructUtils.convert(bo, SysSocial.class);
+ validEntityBeforeSave(update);
+ return sysSocialMapper.update(update) > 0;
+ }
+
+ /**
+ * 保存前的数据校验
+ */
+ private void validEntityBeforeSave(SysSocial entity) {
+ //TODO 做一些数据校验,如唯一约束
+ }
+
+
+ /**
+ * 删除社会化关系
+ */
+ @Override
+ public Boolean deleteWithValidById(Long socialId) {
+ return sysSocialMapper.deleteById(socialId) > 0;
+ }
+
+
+ /**
+ * 根据 authId 查询用户信息
+ *
+ * @param authId 认证id
+ * @return 授权信息
+ */
+ @Override
+ public List selectListByAuthId(String authId) {
+ return sysSocialMapper.selectListByQueryAs(QueryWrapper.create().from(SYS_SOCIAL).where(SYS_SOCIAL.AUTH_ID.eq(authId)), SysSocialVo.class);
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
index 893423a..d90acd8 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -140,8 +140,7 @@ public class SysUserServiceImpl extends BaseServiceImpl
SYS_DEPT.DEPT_ID, SYS_DEPT.PARENT_ID, SYS_DEPT.ANCESTORS, SYS_DEPT.DEPT_NAME, SYS_DEPT.ORDER_NUM, SYS_DEPT.LEADER, SYS_DEPT.STATUS.as("dept_status")
))
.from(SYS_USER.as("u"))
- .leftJoin(SYS_DEPT).as("d").on(SYS_DEPT.DEPT_ID.eq(SYS_USER.DEPT_ID))
- .where(SYS_USER.DEL_FLAG.eq(0));
+ .leftJoin(SYS_DEPT).as("d").on(SYS_DEPT.DEPT_ID.eq(SYS_USER.DEPT_ID));
//.leftJoin(SYS_USER_ROLE).as("ur").on(SYS_USER_ROLE.USER_ID.eq(SYS_USER.USER_ID))
//.leftJoin(SYS_ROLE).as("r").on(SYS_ROLE.ROLE_ID.eq(SYS_USER_ROLE.ROLE_ID));
}
@@ -276,12 +275,12 @@ public class SysUserServiceImpl extends BaseServiceImpl
/**
* 登录时通过用户名、租户编号查询用户(不走Mybatis-Flex租户插件)
*
- * @param userName 用户名
* @param tenantId 租户编号
+ * @param userName 用户名
* @return 用户对象信息
*/
@Override
- public SysUserVo selectTenantUserByUserName(String userName, Long tenantId) {
+ public SysUserVo selectTenantUserByUserName(Long tenantId, String userName) {
return TenantHelper.ignore(() -> {
QueryWrapper queryWrapper = buildOneQueryWrapper()
.where(SYS_USER.TENANT_ID.eq(tenantId))
@@ -291,19 +290,54 @@ public class SysUserServiceImpl extends BaseServiceImpl
}
/**
- * 通过邮箱查询用户
+ * 登录时通过用户名、租户编号查询用户(不走Mybatis-Flex租户插件)
*
+ * @param tenantId 租户编号
+ * @param phonenumber 手机号
+ * @return 用户对象信息
+ */
+ @Override
+ public SysUserVo selectTenantUserByPhonenumber(Long tenantId, String phonenumber) {
+ return TenantHelper.ignore(() -> {
+ QueryWrapper queryWrapper = buildOneQueryWrapper()
+ .where(SYS_USER.TENANT_ID.eq(tenantId))
+ .and(SYS_USER.PHONENUMBER.eq(phonenumber));
+ return this.getOneAs(queryWrapper, SysUserVo.class);
+ });
+ }
+
+ /**
+ * 登录时通过租户编号、邮箱查询用户(不走Mybatis-Flex租户插件)
+ *
+ * @param tenantId 租户编号
* @param email 邮箱
* @return 用户对象信息
*/
@Override
- public SysUserVo selectUserByEmail(String email) {
- QueryWrapper queryWrapper = buildOneQueryWrapper();
- queryWrapper.where(SYS_USER.DEL_FLAG.eq(0));
- if (StringUtils.isNotEmpty(email)) {
- queryWrapper.and(SYS_USER.EMAIL.eq(email));
- }
- return this.getOneAs(queryWrapper, SysUserVo.class);
+ public SysUserVo selectTenantUserByEmail(Long tenantId, String email) {
+ return TenantHelper.ignore(() -> {
+ QueryWrapper queryWrapper = buildOneQueryWrapper()
+ .where(SYS_USER.TENANT_ID.eq(tenantId))
+ .and(SYS_USER.EMAIL.eq(email));
+ return this.getOneAs(queryWrapper, SysUserVo.class);
+ });
+ }
+
+ /**
+ * 登录时通过租户编号、邮箱查询用户(不走Mybatis-Flex租户插件)
+ *
+ * @param tenantId 租户编号
+ * @param userId 用户id
+ * @return 用户对象信息
+ */
+ @Override
+ public SysUserVo selectTenantUserById(Long tenantId, Long userId) {
+ return TenantHelper.ignore(() -> {
+ QueryWrapper queryWrapper = buildOneQueryWrapper()
+ .where(SYS_USER.TENANT_ID.eq(tenantId))
+ .and(SYS_USER.USER_ID.eq(userId));
+ return this.getOneAs(queryWrapper, SysUserVo.class);
+ });
}
/**
diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysSocialMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysSocialMapper.xml
new file mode 100644
index 0000000..b734b77
--- /dev/null
+++ b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysSocialMapper.xml
@@ -0,0 +1,7 @@
+
+
+
+
+