diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/LoginUserApi.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/LoginUserApi.java
index 968b683ed..7f0f77118 100644
--- a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/LoginUserApi.java
+++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/LoginUserApi.java
@@ -27,6 +27,8 @@ package cn.stylefeng.roses.kernel.auth.api;
import cn.stylefeng.roses.kernel.auth.api.exception.AuthException;
import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser;
+import java.util.function.Consumer;
+
/**
* 当前登陆用户相关的一系列方法
*
@@ -95,4 +97,35 @@ public interface LoginUserApi {
*/
Long getCurrentUserCompanyId();
+ /**
+ * 切换当前登录用户为指定用户id
+ *
+ * 仅应用在当前线程环境中,使用后请及时调用endSwitch()方法
+ *
+ * @param userId 切换到指定用户身份
+ * @author fengshuonan
+ * @since 2023/11/16 21:03
+ */
+ LoginUser switchTo(Long userId);
+
+ /**
+ * 结束临时身份切换
+ *
+ * 仅应用在当前线程环境中
+ *
+ * @author fengshuonan
+ * @since 2023/11/16 21:03
+ */
+ void endSwitch();
+
+ /**
+ * 切换身份并执行一次函数回调
+ *
+ * @param userId 指定账号id
+ * @param consumer 要执行的方法
+ * @author fengshuonan
+ * @since 2023/11/16 21:12
+ */
+ void switchTo(Long userId, Consumer consumer);
+
}
diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/constants/AuthConstants.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/constants/AuthConstants.java
index 44c5fa4d9..8d7a8adb2 100644
--- a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/constants/AuthConstants.java
+++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/constants/AuthConstants.java
@@ -122,4 +122,9 @@ public interface AuthConstants {
*/
String CA_CLIENT_TOKEN_CACHE_PREFIX = "CA_CLIENT:TOKEN:";
+ /**
+ * 临时Token,用在身份切换过程使用
+ */
+ String TEMP_TOKEN = "tempToken";
+
}
diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/LoginUserImpl.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/LoginUserImpl.java
index b67f2c71e..302b145f5 100644
--- a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/LoginUserImpl.java
+++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/LoginUserImpl.java
@@ -24,8 +24,12 @@
*/
package cn.stylefeng.roses.kernel.auth.auth;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.bean.copier.CopyOptions;
+import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.kernel.auth.api.LoginUserApi;
import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi;
+import cn.stylefeng.roses.kernel.auth.api.constants.AuthConstants;
import cn.stylefeng.roses.kernel.auth.api.context.LoginContext;
import cn.stylefeng.roses.kernel.auth.api.context.LoginUserHolder;
import cn.stylefeng.roses.kernel.auth.api.exception.AuthException;
@@ -35,9 +39,11 @@ import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser;
import cn.stylefeng.roses.kernel.sys.api.OrganizationServiceApi;
import cn.stylefeng.roses.kernel.sys.api.SysUserServiceApi;
import cn.stylefeng.roses.kernel.sys.api.pojo.org.CompanyDeptDTO;
+import cn.stylefeng.roses.kernel.sys.api.pojo.user.TempLoginUserInfo;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
+import java.util.function.Consumer;
/**
* 当前登陆用户的接口实现
@@ -144,4 +150,42 @@ public class LoginUserImpl implements LoginUserApi {
return orgCompanyInfo.getCompanyId();
}
+ @Override
+ public LoginUser switchTo(Long userId) {
+
+ if (ObjectUtil.isEmpty(userId)) {
+ return null;
+ }
+
+ // 获取用户的基本信息
+ TempLoginUserInfo tempLoginUserInfo = sysUserServiceApi.createTempUserInfo(userId);
+ if (tempLoginUserInfo == null) {
+ return null;
+ }
+
+ // 创建临时登录用户
+ LoginUser loginUser = new LoginUser();
+ BeanUtil.copyProperties(tempLoginUserInfo, loginUser, CopyOptions.create().ignoreError());
+
+ // 设置用户的临时token
+ loginUser.setToken(AuthConstants.TEMP_TOKEN);
+
+ // 放入线程变量中
+ LoginUserHolder.set(loginUser);
+
+ return loginUser;
+ }
+
+ @Override
+ public void endSwitch() {
+ LoginUserHolder.remove();
+ }
+
+ @Override
+ public void switchTo(Long userId, Consumer consumer) {
+ this.switchTo(userId);
+ consumer.accept(userId);
+ this.endSwitch();
+ }
+
}
diff --git a/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/sys/api/SysUserServiceApi.java b/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/sys/api/SysUserServiceApi.java
index 5ea50a465..b23b27a62 100644
--- a/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/sys/api/SysUserServiceApi.java
+++ b/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/sys/api/SysUserServiceApi.java
@@ -24,10 +24,7 @@
*/
package cn.stylefeng.roses.kernel.sys.api;
-import cn.stylefeng.roses.kernel.sys.api.pojo.user.OnlineUserItem;
-import cn.stylefeng.roses.kernel.sys.api.pojo.user.SimpleUserDTO;
-import cn.stylefeng.roses.kernel.sys.api.pojo.user.UserInfoDetailDTO;
-import cn.stylefeng.roses.kernel.sys.api.pojo.user.UserValidateDTO;
+import cn.stylefeng.roses.kernel.sys.api.pojo.user.*;
import java.util.List;
@@ -144,4 +141,12 @@ public interface SysUserServiceApi {
*/
void lockUserStatus(String tenantCode, String account);
+ /**
+ * 创建指定的用户临时身份信息
+ *
+ * @author fengshuonan
+ * @since 2023/11/16 21:39
+ */
+ TempLoginUserInfo createTempUserInfo(Long userId);
+
}
diff --git a/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/sys/api/pojo/user/TempLoginUserInfo.java b/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/sys/api/pojo/user/TempLoginUserInfo.java
new file mode 100644
index 000000000..95a26ad19
--- /dev/null
+++ b/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/sys/api/pojo/user/TempLoginUserInfo.java
@@ -0,0 +1,41 @@
+package cn.stylefeng.roses.kernel.sys.api.pojo.user;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 临时用户身份信息的包装
+ *
+ * @author fengshuonan
+ * @since 2023/11/16 21:38
+ */
+@Data
+public class TempLoginUserInfo {
+
+ /**
+ * 用户id
+ */
+ private Long userId;
+
+ /**
+ * 用户账号
+ */
+ private String account;
+
+ /**
+ * 租户id
+ */
+ private Long tenantId;
+
+ /**
+ * 登录时候的IP
+ */
+ private String loginIp;
+
+ /**
+ * 登录时间
+ */
+ private Date loginTime;
+
+}
diff --git a/kernel-s-system/system-business-hr/src/main/java/cn/stylefeng/roses/kernel/sys/modular/user/service/impl/SysUserServiceImpl.java b/kernel-s-system/system-business-hr/src/main/java/cn/stylefeng/roses/kernel/sys/modular/user/service/impl/SysUserServiceImpl.java
index 6ddaa3d72..c192221ab 100644
--- a/kernel-s-system/system-business-hr/src/main/java/cn/stylefeng/roses/kernel/sys/modular/user/service/impl/SysUserServiceImpl.java
+++ b/kernel-s-system/system-business-hr/src/main/java/cn/stylefeng/roses/kernel/sys/modular/user/service/impl/SysUserServiceImpl.java
@@ -675,6 +675,39 @@ public class SysUserServiceImpl extends ServiceImpl impl
}
}
+ @Override
+ public TempLoginUserInfo createTempUserInfo(Long userId) {
+
+ if (ObjectUtil.isEmpty(userId)) {
+ return null;
+ }
+
+ // 查询用户id对应的用户信息
+ LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
+ wrapper.eq(SysUser::getUserId, userId);
+ wrapper.select(SysUser::getUserId, SysUser::getAccount, SysUser::getTenantId, SysUser::getLastLoginIp, SysUser::getLastLoginTime);
+ SysUser sysUser = null;
+ try {
+ TenantSwitchHolder.set(false);
+ sysUser = this.getOne(wrapper);
+ } finally {
+ TenantSwitchHolder.remove();
+ }
+
+ if (sysUser == null) {
+ return null;
+ }
+
+ TempLoginUserInfo tempLoginUserInfo = new TempLoginUserInfo();
+ tempLoginUserInfo.setUserId(sysUser.getUserId());
+ tempLoginUserInfo.setAccount(sysUser.getAccount());
+ tempLoginUserInfo.setTenantId(sysUser.getTenantId());
+ tempLoginUserInfo.setLoginTime(sysUser.getLastLoginTime());
+ tempLoginUserInfo.setLoginIp(sysUser.getLastLoginIp());
+
+ return tempLoginUserInfo;
+ }
+
/**
* 获取信息
*