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; + } + /** * 获取信息 *