diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/TenantCodeGetApi.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/TenantCodeGetApi.java
new file mode 100644
index 000000000..38910f297
--- /dev/null
+++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/TenantCodeGetApi.java
@@ -0,0 +1,21 @@
+package cn.stylefeng.roses.kernel.auth.api;
+
+/**
+ * 租户编码的接口,通过租户编码获取到租户ID
+ *
+ * 一般用在登录接口,通过租户的编码获取租户的id信息
+ *
+ * @author fengshuonan
+ * @since 2023/8/31 23:49
+ */
+public interface TenantCodeGetApi {
+
+ /**
+ * 通过租户编码获取租户的ID
+ *
+ * @author fengshuonan
+ * @since 2023/8/31 23:50
+ */
+ Long getTenantIdByCode(String tenantCode);
+
+}
diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java
index cf11f0ab6..292bdb11b 100644
--- a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java
+++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/AuthServiceImpl.java
@@ -238,12 +238,12 @@ public class AuthServiceImpl implements AuthServiceApi {
public LoginUser createNewLoginInfo(String token, DefaultJwtPayload defaultJwtPayload) {
// 获取用户的信息
- String account = defaultJwtPayload.getAccount();
+ Long userId = defaultJwtPayload.getUserId();
LoginUser loginUser;
// 获取用户信息
- UserValidateDTO userValidateDTO = sysUserServiceApi.getUserLoginValidateDTO(account);
+ UserValidateDTO userValidateDTO = sysUserServiceApi.getUserLoginValidateDTO(userId);
// 创建登录用户
loginUser = new LoginUser(userValidateDTO.getUserId(), token);
diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/DefaultTenantCodeProvider.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/DefaultTenantCodeProvider.java
new file mode 100644
index 000000000..14d576f0b
--- /dev/null
+++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/DefaultTenantCodeProvider.java
@@ -0,0 +1,34 @@
+package cn.stylefeng.roses.kernel.auth.auth;
+
+import cn.stylefeng.roses.kernel.auth.api.TenantCodeGetApi;
+import cn.stylefeng.roses.kernel.sys.api.expander.TenantConfigExpander;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 获取默认的租户id
+ *
+ * 开源版不提供租户管理的功能,只能提供单租户编码的维护,也就是默认租户
+ *
+ * @author fengshuonan
+ * @since 2023/9/1 0:38
+ */
+@Slf4j
+public class DefaultTenantCodeProvider implements TenantCodeGetApi {
+
+ /**
+ * 一个不存在的租户id
+ */
+ public static final Long DEFAULT_NONE_TENANT_ID = -999L;
+
+ @Override
+ public Long getTenantIdByCode(String tenantCode) {
+ Long defaultRootTenantId = TenantConfigExpander.getDefaultRootTenantId();
+ if (defaultRootTenantId.toString().equals(tenantCode)) {
+ return defaultRootTenantId;
+ } else {
+ log.warn("当前系统为单租户系统,不支持多租户功能!");
+ return DEFAULT_NONE_TENANT_ID;
+ }
+ }
+
+}
diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/LoginService.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/LoginService.java
index f533b1ae6..25eb426b7 100644
--- a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/LoginService.java
+++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/LoginService.java
@@ -8,6 +8,7 @@ import cn.hutool.http.HttpResponse;
import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi;
import cn.stylefeng.roses.kernel.auth.api.SsoServerApi;
import cn.stylefeng.roses.kernel.auth.api.TempSecretApi;
+import cn.stylefeng.roses.kernel.auth.api.TenantCodeGetApi;
import cn.stylefeng.roses.kernel.auth.api.constants.AuthConstants;
import cn.stylefeng.roses.kernel.auth.api.constants.LoginCacheConstants;
import cn.stylefeng.roses.kernel.auth.api.context.AuthJwtContext;
@@ -80,6 +81,9 @@ public class LoginService {
@Resource
private PasswordStoredEncryptApi passwordStoredEncryptApi;
+ @Resource
+ private TenantCodeGetApi tenantCodeGetApi;
+
/**
* 登录的真正业务逻辑
*
@@ -125,13 +129,12 @@ public class LoginService {
}
}
- // 4.1 通过租户编码获取租户id,如果租户参数没传,则默认填充根租户的id todo
+ // 4.1 通过租户编码获取租户id,如果租户参数没传,则默认填充根租户的id
String tenantCode = loginRequest.getTenantCode();
-
-
+ Long tenantId = tenantCodeGetApi.getTenantIdByCode(tenantCode);
// 5. 获取用户密码的加密值和用户的状态
- UserValidateDTO userValidateInfo = sysUserServiceApi.getUserLoginValidateDTO(loginRequest.getAccount());
+ UserValidateDTO userValidateInfo = sysUserServiceApi.getUserLoginValidateDTO(tenantId, loginRequest.getAccount());
// 6. 校验用户密码是否正确
validateUserPassword(validatePassword, loginErrorCount, loginRequest, userValidateInfo);
diff --git a/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/AuthAutoConfiguration.java b/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/AuthAutoConfiguration.java
index 13f6de930..a6e9a1a50 100644
--- a/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/AuthAutoConfiguration.java
+++ b/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/AuthAutoConfiguration.java
@@ -25,11 +25,13 @@
package cn.stylefeng.roses.kernel.auth.starter;
import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi;
+import cn.stylefeng.roses.kernel.auth.api.TenantCodeGetApi;
import cn.stylefeng.roses.kernel.auth.api.expander.AuthConfigExpander;
import cn.stylefeng.roses.kernel.auth.api.password.PasswordStoredEncryptApi;
import cn.stylefeng.roses.kernel.auth.api.password.PasswordTransferEncryptApi;
import cn.stylefeng.roses.kernel.auth.api.pojo.auth.PwdRsaSecretProperties;
import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser;
+import cn.stylefeng.roses.kernel.auth.auth.DefaultTenantCodeProvider;
import cn.stylefeng.roses.kernel.auth.password.BcryptPasswordStoredEncrypt;
import cn.stylefeng.roses.kernel.auth.password.RsaPasswordTransferEncrypt;
import cn.stylefeng.roses.kernel.auth.session.DefaultSessionManager;
@@ -111,7 +113,8 @@ public class AuthAutoConfiguration {
*/
@Bean
@ConditionalOnMissingBean(SessionManagerApi.class)
- public SessionManagerApi sessionManagerApi(CacheOperatorApi loginUserCache, CacheOperatorApi> allPlaceLoginTokenCache) {
+ public SessionManagerApi sessionManagerApi(CacheOperatorApi loginUserCache,
+ CacheOperatorApi> allPlaceLoginTokenCache) {
Long sessionExpiredSeconds = AuthConfigExpander.getSessionExpiredSeconds();
return new DefaultSessionManager(loginUserCache, allPlaceLoginTokenCache, sessionExpiredSeconds);
}
@@ -124,8 +127,21 @@ public class AuthAutoConfiguration {
*/
@Bean
@ConditionalOnMissingBean(ClearInvalidLoginUserCacheTimer.class)
- public ClearInvalidLoginUserCacheTimer clearInvalidLoginUserCacheTimer(CacheOperatorApi loginUserCache, CacheOperatorApi> allPlaceLoginTokenCache) {
+ public ClearInvalidLoginUserCacheTimer clearInvalidLoginUserCacheTimer(CacheOperatorApi loginUserCache,
+ CacheOperatorApi> allPlaceLoginTokenCache) {
return new ClearInvalidLoginUserCacheTimer(loginUserCache, allPlaceLoginTokenCache);
}
+ /**
+ * 通过租户编码获取租户id的查询接口
+ *
+ * @author fengshuonan
+ * @since 2023/9/1 0:52
+ */
+ @Bean
+ @ConditionalOnMissingBean(TenantCodeGetApi.class)
+ public TenantCodeGetApi tenantCodeGetApi() {
+ return new DefaultTenantCodeProvider();
+ }
+
}
diff --git a/kernel-d-db/db-sdk-mp/src/main/java/cn/stylefeng/roses/kernel/db/mp/tenant/ProjectTenantInterceptor.java b/kernel-d-db/db-sdk-mp/src/main/java/cn/stylefeng/roses/kernel/db/mp/tenant/ProjectTenantInterceptor.java
index e67c33b84..fc6809c3d 100644
--- a/kernel-d-db/db-sdk-mp/src/main/java/cn/stylefeng/roses/kernel/db/mp/tenant/ProjectTenantInterceptor.java
+++ b/kernel-d-db/db-sdk-mp/src/main/java/cn/stylefeng/roses/kernel/db/mp/tenant/ProjectTenantInterceptor.java
@@ -5,6 +5,7 @@ import cn.stylefeng.roses.kernel.auth.api.context.LoginContext;
import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser;
import cn.stylefeng.roses.kernel.db.api.pojo.tenant.TenantTableProperties;
import cn.stylefeng.roses.kernel.db.mp.tenant.holder.TenantIdHolder;
+import cn.stylefeng.roses.kernel.db.mp.tenant.holder.TenantSwitchHolder;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
@@ -52,6 +53,13 @@ public class ProjectTenantInterceptor implements TenantLineHandler {
@Override
public boolean ignoreTable(String tableName) {
+ // 1. 优先从线程变量中获取,这个优先级最高
+ Boolean openFlag = TenantSwitchHolder.get();
+ if (openFlag != null && !openFlag) {
+ return true;
+ }
+
+ // 2. 第2步,从系统配置中获取,是否开启此table的开关
if (tenantTableProperties == null) {
return true;
}
diff --git a/kernel-d-db/db-sdk-mp/src/main/java/cn/stylefeng/roses/kernel/db/mp/tenant/holder/TenantRemoveThreadLocalHolder.java b/kernel-d-db/db-sdk-mp/src/main/java/cn/stylefeng/roses/kernel/db/mp/tenant/holder/TenantRemoveThreadLocalHolder.java
index 0d63dd5df..4c9af66e6 100644
--- a/kernel-d-db/db-sdk-mp/src/main/java/cn/stylefeng/roses/kernel/db/mp/tenant/holder/TenantRemoveThreadLocalHolder.java
+++ b/kernel-d-db/db-sdk-mp/src/main/java/cn/stylefeng/roses/kernel/db/mp/tenant/holder/TenantRemoveThreadLocalHolder.java
@@ -15,6 +15,7 @@ public class TenantRemoveThreadLocalHolder implements RemoveThreadLocalApi {
@Override
public void removeThreadLocalAction() {
TenantIdHolder.remove();
+ TenantSwitchHolder.remove();
}
}
diff --git a/kernel-d-db/db-sdk-mp/src/main/java/cn/stylefeng/roses/kernel/db/mp/tenant/holder/TenantSwitchHolder.java b/kernel-d-db/db-sdk-mp/src/main/java/cn/stylefeng/roses/kernel/db/mp/tenant/holder/TenantSwitchHolder.java
new file mode 100644
index 000000000..19542e737
--- /dev/null
+++ b/kernel-d-db/db-sdk-mp/src/main/java/cn/stylefeng/roses/kernel/db/mp/tenant/holder/TenantSwitchHolder.java
@@ -0,0 +1,43 @@
+package cn.stylefeng.roses.kernel.db.mp.tenant.holder;
+
+/**
+ * 是否开启租户过滤的开关,此优先级最高
+ *
+ * @author fengshuonan
+ * @since 2023/9/1 0:09
+ */
+public class TenantSwitchHolder {
+
+ private static final ThreadLocal TENANT_SWITCH_FLAG_HOLDER = new ThreadLocal<>();
+
+ /**
+ * 设置是否开启租户过滤,true开启,false关闭
+ *
+ * @author fengshuonan
+ * @since 2023/9/1 0:11
+ */
+ public static void set(Boolean tenantSwitch) {
+ TENANT_SWITCH_FLAG_HOLDER.set(tenantSwitch);
+ }
+
+ /**
+ * 获取租户开启开关
+ *
+ * @author fengshuonan
+ * @since 2023/9/1 0:11
+ */
+ public static Boolean get() {
+ return TENANT_SWITCH_FLAG_HOLDER.get();
+ }
+
+ /**
+ * 清空开关
+ *
+ * @author fengshuonan
+ * @since 2023/9/1 0:11
+ */
+ public static void remove() {
+ TENANT_SWITCH_FLAG_HOLDER.remove();
+ }
+
+}
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 27548c919..92ff15cb9 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
@@ -58,11 +58,21 @@ public interface SysUserServiceApi {
/**
* 获取用于用户校验的
*
- * @param account 用户账号
+ * @param tenantId 指定租户id
+ * @param account 用户账号
* @author fengshuonan
* @since 2023/6/17 21:56
*/
- UserValidateDTO getUserLoginValidateDTO(String account);
+ UserValidateDTO getUserLoginValidateDTO(Long tenantId, String account);
+
+ /**
+ * 通过用户id创建用户的校验信息
+ *
+ * @param userId 用户id
+ * @author fengshuonan
+ * @since 2023/6/17 21:56
+ */
+ UserValidateDTO getUserLoginValidateDTO(Long userId);
/**
* 更新用户的登录ip和最后登录时间
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 b2d1976c6..4fcb068ca 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
@@ -12,6 +12,8 @@ import cn.stylefeng.roses.kernel.db.api.factory.PageFactory;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.entity.BaseEntity;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
+import cn.stylefeng.roses.kernel.db.mp.tenant.holder.TenantIdHolder;
+import cn.stylefeng.roses.kernel.db.mp.tenant.holder.TenantSwitchHolder;
import cn.stylefeng.roses.kernel.file.api.FileInfoApi;
import cn.stylefeng.roses.kernel.file.api.constants.FileConstants;
import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum;
@@ -359,11 +361,42 @@ public class SysUserServiceImpl extends ServiceImpl impl
}
@Override
- public UserValidateDTO getUserLoginValidateDTO(String account) {
+ public UserValidateDTO getUserLoginValidateDTO(Long tenantId, String account) {
LambdaQueryWrapper sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
sysUserLambdaQueryWrapper.eq(SysUser::getAccount, account);
sysUserLambdaQueryWrapper.select(SysUser::getPassword, SysUser::getPasswordSalt, SysUser::getStatusFlag, SysUser::getUserId);
- SysUser sysUserServiceOne = this.getOne(sysUserLambdaQueryWrapper, false);
+
+ // 单独填充租户id
+ SysUser sysUserServiceOne;
+ try {
+ TenantIdHolder.set(tenantId);
+ sysUserServiceOne = this.getOne(sysUserLambdaQueryWrapper, false);
+ } finally {
+ TenantIdHolder.remove();
+ }
+
+ if (sysUserServiceOne == null) {
+ throw new ServiceException(SysUserExceptionEnum.ACCOUNT_NOT_EXIST);
+ }
+
+ return new UserValidateDTO(sysUserServiceOne.getUserId(), sysUserServiceOne.getPassword(), sysUserServiceOne.getPasswordSalt(),
+ sysUserServiceOne.getStatusFlag());
+ }
+
+ @Override
+ public UserValidateDTO getUserLoginValidateDTO(Long userId) {
+ LambdaQueryWrapper sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
+ sysUserLambdaQueryWrapper.eq(SysUser::getUserId, userId);
+ sysUserLambdaQueryWrapper.select(SysUser::getPassword, SysUser::getPasswordSalt, SysUser::getStatusFlag, SysUser::getUserId);
+
+ // 单独填充租户id
+ SysUser sysUserServiceOne;
+ try {
+ TenantSwitchHolder.set(false);
+ sysUserServiceOne = this.getOne(sysUserLambdaQueryWrapper, false);
+ } finally {
+ TenantSwitchHolder.remove();
+ }
if (sysUserServiceOne == null) {
throw new ServiceException(SysUserExceptionEnum.ACCOUNT_NOT_EXIST);