first commit

This commit is contained in:
2023-06-11 12:21:49 +08:00
parent 4dcb7c297b
commit d1990dc0e3
7 changed files with 106 additions and 13 deletions

View File

@ -8,13 +8,13 @@ import com.qiaoba.auth.service.OnlineUserService;
import com.qiaoba.auth.utils.TokenUtil; import com.qiaoba.auth.utils.TokenUtil;
import com.qiaoba.common.redis.service.RedisService; import com.qiaoba.common.redis.service.RedisService;
import com.qiaoba.common.web.utils.ResponseUtil; import com.qiaoba.common.web.utils.ResponseUtil;
import com.qiaoba.common.web.utils.UriUtil;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;
@ -40,7 +40,6 @@ public class AuthenticationCoreFilter extends OncePerRequestFilter {
private final AuthConfigProperties authConfigProperties; private final AuthConfigProperties authConfigProperties;
private final AuthConfigApiService authConfigApiService; private final AuthConfigApiService authConfigApiService;
private final AntPathMatcher MATCH = new AntPathMatcher();
@Override @Override
protected void doFilterInternal(HttpServletRequest request, protected void doFilterInternal(HttpServletRequest request,
@ -49,7 +48,7 @@ public class AuthenticationCoreFilter extends OncePerRequestFilter {
// 白名单 放行 // 白名单 放行
for (String uri : authConfigProperties.getWhitelist()) { for (String uri : authConfigProperties.getWhitelist()) {
if (MATCH.match(uri,request.getRequestURI())) { if (UriUtil.match(uri, request.getRequestURI())) {
chain.doFilter(request, response); chain.doFilter(request, response);
return; return;
} }

View File

@ -76,7 +76,7 @@ public class BaseContext {
* *
* @return Boolean * @return Boolean
*/ */
public static Boolean getSchema() { public static Boolean isSchemaMode() {
return SCHEMA_HOLDER.get(); return SCHEMA_HOLDER.get();
} }

View File

@ -25,8 +25,8 @@ public class SchemaInterceptor implements InnerInterceptor {
@Override @Override
public void beforePrepare(StatementHandler sh, Connection conn, Integer transactionTimeout) { public void beforePrepare(StatementHandler sh, Connection conn, Integer transactionTimeout) {
if (Objects.nonNull(BaseContext.getSchema()) && BaseContext.getSchema()) { if (Objects.nonNull(BaseContext.isSchemaMode()) && BaseContext.isSchemaMode()) {
// use qiaoba-1; // eg: use qiaoba-1;
String sql = StrUtil.format("use `{}-{}`;", baseDatabase, BaseContext.getTenantId()); String sql = StrUtil.format("use `{}-{}`;", baseDatabase, BaseContext.getTenantId());
try { try {
conn.createStatement().execute(sql); conn.createStatement().execute(sql);

View File

@ -0,0 +1,29 @@
package com.qiaoba.common.web.utils;
import org.springframework.util.AntPathMatcher;
/**
* UriUtil
*
* @author ailanyin
* @version 1.0
* @since 2023-06-11 12:01:18
*/
public class UriUtil {
private static final AntPathMatcher MATCH = new AntPathMatcher();
private UriUtil() {
}
/**
* 通配符匹配
*
* @param pattern 通配符
* @param path uri
* @return 结果
*/
public static boolean match(String pattern, String path) {
return MATCH.match(pattern, path);
}
}

View File

@ -10,6 +10,7 @@ import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Date; import java.util.Date;
@ -23,6 +24,7 @@ import java.util.Date;
@Data @Data
@EqualsAndHashCode(callSuper = false) @EqualsAndHashCode(callSuper = false)
@TableName("sys_tenant") @TableName("sys_tenant")
@NoArgsConstructor
public class SysTenant extends BaseEntity { public class SysTenant extends BaseEntity {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -85,4 +87,8 @@ public class SysTenant extends BaseEntity {
private String mode; private String mode;
public SysTenant(String tenantId, String status) {
this.tenantId = tenantId;
this.status = status;
}
} }

View File

@ -0,0 +1,33 @@
package com.qiaoba.module.tenant.enums;
import lombok.Getter;
/**
* 租户状态
*
* @author ailanyin
* @version 1.0
* @since 2023/6/5 16:33
*/
@Getter
public enum TenantStatusEnum {
/**
* 禁用
*/
DISABLE("1", "禁用"),
/**
* 过期
*/
EXPIRE("2", "过期");
private final String status;
private final String info;
TenantStatusEnum(String code, String info) {
this.status = code;
this.info = info;
}
}

View File

@ -2,14 +2,17 @@ package com.qiaoba.module.tenant.filters;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.qiaoba.auth.properties.AuthConfigProperties;
import com.qiaoba.common.base.constants.TenantConstant; import com.qiaoba.common.base.constants.TenantConstant;
import com.qiaoba.common.base.context.BaseContext; import com.qiaoba.common.base.context.BaseContext;
import com.qiaoba.common.base.enums.BaseEnum;
import com.qiaoba.common.database.config.DynamicDataSourceConfig; import com.qiaoba.common.database.config.DynamicDataSourceConfig;
import com.qiaoba.common.database.constants.DynamicDatasourceConstant; import com.qiaoba.common.database.constants.DynamicDatasourceConstant;
import com.qiaoba.common.web.utils.ResponseUtil; import com.qiaoba.common.web.utils.ResponseUtil;
import com.qiaoba.common.web.utils.UriUtil;
import com.qiaoba.module.tenant.entity.SysTenant; import com.qiaoba.module.tenant.entity.SysTenant;
import com.qiaoba.module.tenant.enums.TenantStatusEnum;
import com.qiaoba.module.tenant.service.SysTenantService; import com.qiaoba.module.tenant.service.SysTenantService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
@ -32,35 +35,50 @@ import java.util.Objects;
*/ */
@Component @Component
@Order(-10000) @Order(-10000)
@Slf4j
public class DynamicDataSourceFilter extends OncePerRequestFilter { public class DynamicDataSourceFilter extends OncePerRequestFilter {
@Resource @Resource
private SysTenantService sysTenantService; private SysTenantService sysTenantService;
@Resource @Resource
private DynamicDataSourceConfig dynamicDataSourceConfig; private DynamicDataSourceConfig dynamicDataSourceConfig;
@Resource
private AuthConfigProperties authConfigProperties;
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String tenantId = request.getHeader(TenantConstant.HEADER_KEY_TENANT); String tenantId = request.getHeader(TenantConstant.HEADER_KEY_TENANT);
// 主库或没有tenantId // 主系统
if (StrUtil.isBlank(tenantId) if (TenantConstant.DEFAULT_TENANT_ID.equals(tenantId)) {
|| TenantConstant.DEFAULT_TENANT_ID.equals(tenantId)
|| request.getRequestURI().startsWith("/tenant")) {
dynamicDataSourceConfig.setDefaultSetting(); dynamicDataSourceConfig.setDefaultSetting();
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
after();
return; return;
} }
// 白名单
for (String uri : authConfigProperties.getWhitelist()) {
if (UriUtil.match(uri, request.getRequestURI())) {
dynamicDataSourceConfig.setDefaultSetting();
filterChain.doFilter(request, response);
after();
return;
}
}
SysTenant sysTenant = sysTenantService.selectById(tenantId); SysTenant sysTenant = sysTenantService.selectById(tenantId);
// 检查租户是否允许访问
if (checkTenantIsNotAllow(response, sysTenant)) { if (checkTenantIsNotAllow(response, sysTenant)) {
return; return;
} }
// 设置租户信息
before(sysTenant); before(sysTenant);
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
after(); after();
} }
private void before(SysTenant sysTenant) { private void before(SysTenant sysTenant) {
log.debug(StrUtil.format("设置租户信息, 租户ID: {},租户模式: {}", sysTenant.getTenantId(), sysTenant.getMode()));
BaseContext.setTenantId(sysTenant.getTenantId()); BaseContext.setTenantId(sysTenant.getTenantId());
BaseContext.setSchema(sysTenant.getMode().equals(SysTenant.SCHEMA_MODE)); BaseContext.setSchema(sysTenant.getMode().equals(SysTenant.SCHEMA_MODE));
// 数据源模式-设置第三方数据源 // 数据源模式-设置第三方数据源
@ -68,7 +86,7 @@ public class DynamicDataSourceFilter extends OncePerRequestFilter {
//设置当前租户对应的数据源 //设置当前租户对应的数据源
BaseContext.setDataSource(DynamicDatasourceConstant.MASTER_PREFIX + sysTenant.getTenantId()); BaseContext.setDataSource(DynamicDatasourceConstant.MASTER_PREFIX + sysTenant.getTenantId());
} }
// 字段模式/Schema模式-数据源选择默认数据源 // 字段模式 or Schema模式-数据源选择默认数据源
else { else {
BaseContext.setDataSource(DynamicDatasourceConstant.MASTER_PREFIX + TenantConstant.DEFAULT_TENANT_ID); BaseContext.setDataSource(DynamicDatasourceConstant.MASTER_PREFIX + TenantConstant.DEFAULT_TENANT_ID);
} }
@ -77,6 +95,7 @@ public class DynamicDataSourceFilter extends OncePerRequestFilter {
} }
private void after() { private void after() {
log.debug("clear the BaseContext");
BaseContext.clearAllHolder(); BaseContext.clearAllHolder();
} }
@ -93,15 +112,22 @@ public class DynamicDataSourceFilter extends OncePerRequestFilter {
return true; return true;
} }
if (sysTenant.getStatus().equals(BaseEnum.ABNORMAL.getCode())) { if (TenantStatusEnum.DISABLE.getStatus().equals(sysTenant.getStatus())) {
// 封禁状态 // 封禁状态
ResponseUtil.errorAuth(response, 401, "租户已被封禁"); ResponseUtil.errorAuth(response, 401, "租户已被封禁");
return true; return true;
} }
if (TenantStatusEnum.EXPIRE.getStatus().equals(sysTenant.getStatus())) {
// 已过期
ResponseUtil.errorAuth(response, 401, "租户已过期");
return true;
}
if (DateUtil.compare(sysTenant.getExpireTime(), new Date()) < 0) { if (DateUtil.compare(sysTenant.getExpireTime(), new Date()) < 0) {
// 已过期 // 已过期
ResponseUtil.errorAuth(response, 401, "租户已过期"); ResponseUtil.errorAuth(response, 401, "租户已过期");
// 更新租户状态为已过期
sysTenantService.update(new SysTenant(sysTenant.getTenantId(), TenantStatusEnum.EXPIRE.getStatus()));
return true; return true;
} }
return false; return false;