【8.0】【auth】【login】登录改造,增加租户参数传递逻辑

pull/57/head
fengshuonan 2023-09-01 01:02:39 +08:00
parent 17dc0a105c
commit cc0fed9d92
10 changed files with 181 additions and 12 deletions

View File

@ -0,0 +1,21 @@
package cn.stylefeng.roses.kernel.auth.api;
/**
* ID
* <p>
* 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);
}

View File

@ -238,12 +238,12 @@ public class AuthServiceImpl implements AuthServiceApi {
public LoginUser createNewLoginInfo(String token, DefaultJwtPayload defaultJwtPayload) { public LoginUser createNewLoginInfo(String token, DefaultJwtPayload defaultJwtPayload) {
// 获取用户的信息 // 获取用户的信息
String account = defaultJwtPayload.getAccount(); Long userId = defaultJwtPayload.getUserId();
LoginUser loginUser; LoginUser loginUser;
// 获取用户信息 // 获取用户信息
UserValidateDTO userValidateDTO = sysUserServiceApi.getUserLoginValidateDTO(account); UserValidateDTO userValidateDTO = sysUserServiceApi.getUserLoginValidateDTO(userId);
// 创建登录用户 // 创建登录用户
loginUser = new LoginUser(userValidateDTO.getUserId(), token); loginUser = new LoginUser(userValidateDTO.getUserId(), token);

View File

@ -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
* <p>
*
*
* @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;
}
}
}

View File

@ -8,6 +8,7 @@ import cn.hutool.http.HttpResponse;
import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi; import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi;
import cn.stylefeng.roses.kernel.auth.api.SsoServerApi; import cn.stylefeng.roses.kernel.auth.api.SsoServerApi;
import cn.stylefeng.roses.kernel.auth.api.TempSecretApi; 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.AuthConstants;
import cn.stylefeng.roses.kernel.auth.api.constants.LoginCacheConstants; import cn.stylefeng.roses.kernel.auth.api.constants.LoginCacheConstants;
import cn.stylefeng.roses.kernel.auth.api.context.AuthJwtContext; import cn.stylefeng.roses.kernel.auth.api.context.AuthJwtContext;
@ -80,6 +81,9 @@ public class LoginService {
@Resource @Resource
private PasswordStoredEncryptApi passwordStoredEncryptApi; 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(); String tenantCode = loginRequest.getTenantCode();
Long tenantId = tenantCodeGetApi.getTenantIdByCode(tenantCode);
// 5. 获取用户密码的加密值和用户的状态 // 5. 获取用户密码的加密值和用户的状态
UserValidateDTO userValidateInfo = sysUserServiceApi.getUserLoginValidateDTO(loginRequest.getAccount()); UserValidateDTO userValidateInfo = sysUserServiceApi.getUserLoginValidateDTO(tenantId, loginRequest.getAccount());
// 6. 校验用户密码是否正确 // 6. 校验用户密码是否正确
validateUserPassword(validatePassword, loginErrorCount, loginRequest, userValidateInfo); validateUserPassword(validatePassword, loginErrorCount, loginRequest, userValidateInfo);

View File

@ -25,11 +25,13 @@
package cn.stylefeng.roses.kernel.auth.starter; package cn.stylefeng.roses.kernel.auth.starter;
import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi; 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.expander.AuthConfigExpander;
import cn.stylefeng.roses.kernel.auth.api.password.PasswordStoredEncryptApi; 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.password.PasswordTransferEncryptApi;
import cn.stylefeng.roses.kernel.auth.api.pojo.auth.PwdRsaSecretProperties; 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.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.BcryptPasswordStoredEncrypt;
import cn.stylefeng.roses.kernel.auth.password.RsaPasswordTransferEncrypt; import cn.stylefeng.roses.kernel.auth.password.RsaPasswordTransferEncrypt;
import cn.stylefeng.roses.kernel.auth.session.DefaultSessionManager; import cn.stylefeng.roses.kernel.auth.session.DefaultSessionManager;
@ -111,7 +113,8 @@ public class AuthAutoConfiguration {
*/ */
@Bean @Bean
@ConditionalOnMissingBean(SessionManagerApi.class) @ConditionalOnMissingBean(SessionManagerApi.class)
public SessionManagerApi sessionManagerApi(CacheOperatorApi<LoginUser> loginUserCache, CacheOperatorApi<Set<String>> allPlaceLoginTokenCache) { public SessionManagerApi sessionManagerApi(CacheOperatorApi<LoginUser> loginUserCache,
CacheOperatorApi<Set<String>> allPlaceLoginTokenCache) {
Long sessionExpiredSeconds = AuthConfigExpander.getSessionExpiredSeconds(); Long sessionExpiredSeconds = AuthConfigExpander.getSessionExpiredSeconds();
return new DefaultSessionManager(loginUserCache, allPlaceLoginTokenCache, sessionExpiredSeconds); return new DefaultSessionManager(loginUserCache, allPlaceLoginTokenCache, sessionExpiredSeconds);
} }
@ -124,8 +127,21 @@ public class AuthAutoConfiguration {
*/ */
@Bean @Bean
@ConditionalOnMissingBean(ClearInvalidLoginUserCacheTimer.class) @ConditionalOnMissingBean(ClearInvalidLoginUserCacheTimer.class)
public ClearInvalidLoginUserCacheTimer clearInvalidLoginUserCacheTimer(CacheOperatorApi<LoginUser> loginUserCache, CacheOperatorApi<Set<String>> allPlaceLoginTokenCache) { public ClearInvalidLoginUserCacheTimer clearInvalidLoginUserCacheTimer(CacheOperatorApi<LoginUser> loginUserCache,
CacheOperatorApi<Set<String>> allPlaceLoginTokenCache) {
return new ClearInvalidLoginUserCacheTimer(loginUserCache, 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();
}
} }

View File

@ -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.auth.api.pojo.login.LoginUser;
import cn.stylefeng.roses.kernel.db.api.pojo.tenant.TenantTableProperties; 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.TenantIdHolder;
import cn.stylefeng.roses.kernel.db.mp.tenant.holder.TenantSwitchHolder;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler; import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.LongValue;
@ -52,6 +53,13 @@ public class ProjectTenantInterceptor implements TenantLineHandler {
@Override @Override
public boolean ignoreTable(String tableName) { public boolean ignoreTable(String tableName) {
// 1. 优先从线程变量中获取,这个优先级最高
Boolean openFlag = TenantSwitchHolder.get();
if (openFlag != null && !openFlag) {
return true;
}
// 2. 第2步从系统配置中获取是否开启此table的开关
if (tenantTableProperties == null) { if (tenantTableProperties == null) {
return true; return true;
} }

View File

@ -15,6 +15,7 @@ public class TenantRemoveThreadLocalHolder implements RemoveThreadLocalApi {
@Override @Override
public void removeThreadLocalAction() { public void removeThreadLocalAction() {
TenantIdHolder.remove(); TenantIdHolder.remove();
TenantSwitchHolder.remove();
} }
} }

View File

@ -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<Boolean> TENANT_SWITCH_FLAG_HOLDER = new ThreadLocal<>();
/**
* truefalse
*
* @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();
}
}

View File

@ -58,11 +58,21 @@ public interface SysUserServiceApi {
/** /**
* *
* *
* @param account * @param tenantId id
* @param account
* @author fengshuonan * @author fengshuonan
* @since 2023/6/17 21:56 * @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 * ip

View File

@ -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.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.entity.BaseEntity; 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.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.FileInfoApi;
import cn.stylefeng.roses.kernel.file.api.constants.FileConstants; import cn.stylefeng.roses.kernel.file.api.constants.FileConstants;
import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum; import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum;
@ -359,11 +361,42 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
} }
@Override @Override
public UserValidateDTO getUserLoginValidateDTO(String account) { public UserValidateDTO getUserLoginValidateDTO(Long tenantId, String account) {
LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
sysUserLambdaQueryWrapper.eq(SysUser::getAccount, account); sysUserLambdaQueryWrapper.eq(SysUser::getAccount, account);
sysUserLambdaQueryWrapper.select(SysUser::getPassword, SysUser::getPasswordSalt, SysUser::getStatusFlag, SysUser::getUserId); 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<SysUser> 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) { if (sysUserServiceOne == null) {
throw new ServiceException(SysUserExceptionEnum.ACCOUNT_NOT_EXIST); throw new ServiceException(SysUserExceptionEnum.ACCOUNT_NOT_EXIST);