From d1990dc0e3f82ccebb6b05b3ff18c48a45e6a33d Mon Sep 17 00:00:00 2001 From: ailanyin Date: Sun, 11 Jun 2023 12:21:49 +0800 Subject: [PATCH] first commit --- .../filters/AuthenticationCoreFilter.java | 5 +-- .../common/base/context/BaseContext.java | 2 +- .../interceptors/SchemaInterceptor.java | 4 +- .../com/qiaoba/common/web/utils/UriUtil.java | 29 ++++++++++++++ .../module/tenant/entity/SysTenant.java | 6 +++ .../module/tenant/enums/TenantStatusEnum.java | 33 +++++++++++++++ .../filters/DynamicDataSourceFilter.java | 40 +++++++++++++++---- 7 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 qiaoba-commons/qiaoba-common-web/src/main/java/com/qiaoba/common/web/utils/UriUtil.java create mode 100644 qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/enums/TenantStatusEnum.java diff --git a/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/AuthenticationCoreFilter.java b/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/AuthenticationCoreFilter.java index 926c4b9..000a4dd 100644 --- a/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/AuthenticationCoreFilter.java +++ b/qiaoba-auth/src/main/java/com/qiaoba/auth/filters/AuthenticationCoreFilter.java @@ -8,13 +8,13 @@ import com.qiaoba.auth.service.OnlineUserService; import com.qiaoba.auth.utils.TokenUtil; import com.qiaoba.common.redis.service.RedisService; import com.qiaoba.common.web.utils.ResponseUtil; +import com.qiaoba.common.web.utils.UriUtil; import lombok.RequiredArgsConstructor; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.util.AntPathMatcher; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; @@ -40,7 +40,6 @@ public class AuthenticationCoreFilter extends OncePerRequestFilter { private final AuthConfigProperties authConfigProperties; private final AuthConfigApiService authConfigApiService; - private final AntPathMatcher MATCH = new AntPathMatcher(); @Override protected void doFilterInternal(HttpServletRequest request, @@ -49,7 +48,7 @@ public class AuthenticationCoreFilter extends OncePerRequestFilter { // 白名单 放行 for (String uri : authConfigProperties.getWhitelist()) { - if (MATCH.match(uri,request.getRequestURI())) { + if (UriUtil.match(uri, request.getRequestURI())) { chain.doFilter(request, response); return; } diff --git a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/context/BaseContext.java b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/context/BaseContext.java index 9abee7d..72a7d1d 100644 --- a/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/context/BaseContext.java +++ b/qiaoba-commons/qiaoba-common-base/src/main/java/com/qiaoba/common/base/context/BaseContext.java @@ -76,7 +76,7 @@ public class BaseContext { * * @return Boolean */ - public static Boolean getSchema() { + public static Boolean isSchemaMode() { return SCHEMA_HOLDER.get(); } diff --git a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/interceptors/SchemaInterceptor.java b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/interceptors/SchemaInterceptor.java index c01be6d..f64ca5b 100644 --- a/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/interceptors/SchemaInterceptor.java +++ b/qiaoba-commons/qiaoba-common-datasource/src/main/java/com/qiaoba/common/database/interceptors/SchemaInterceptor.java @@ -25,8 +25,8 @@ public class SchemaInterceptor implements InnerInterceptor { @Override public void beforePrepare(StatementHandler sh, Connection conn, Integer transactionTimeout) { - if (Objects.nonNull(BaseContext.getSchema()) && BaseContext.getSchema()) { - // use qiaoba-1; + if (Objects.nonNull(BaseContext.isSchemaMode()) && BaseContext.isSchemaMode()) { + // eg: use qiaoba-1; String sql = StrUtil.format("use `{}-{}`;", baseDatabase, BaseContext.getTenantId()); try { conn.createStatement().execute(sql); diff --git a/qiaoba-commons/qiaoba-common-web/src/main/java/com/qiaoba/common/web/utils/UriUtil.java b/qiaoba-commons/qiaoba-common-web/src/main/java/com/qiaoba/common/web/utils/UriUtil.java new file mode 100644 index 0000000..ceba62d --- /dev/null +++ b/qiaoba-commons/qiaoba-common-web/src/main/java/com/qiaoba/common/web/utils/UriUtil.java @@ -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); + } +} diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/entity/SysTenant.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/entity/SysTenant.java index 006b11f..445d38a 100644 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/entity/SysTenant.java +++ b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/entity/SysTenant.java @@ -10,6 +10,7 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import java.util.Date; @@ -23,6 +24,7 @@ import java.util.Date; @Data @EqualsAndHashCode(callSuper = false) @TableName("sys_tenant") +@NoArgsConstructor public class SysTenant extends BaseEntity { private static final long serialVersionUID = 1L; @@ -85,4 +87,8 @@ public class SysTenant extends BaseEntity { private String mode; + public SysTenant(String tenantId, String status) { + this.tenantId = tenantId; + this.status = status; + } } diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/enums/TenantStatusEnum.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/enums/TenantStatusEnum.java new file mode 100644 index 0000000..03c2df8 --- /dev/null +++ b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/enums/TenantStatusEnum.java @@ -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; + } +} diff --git a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/filters/DynamicDataSourceFilter.java b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/filters/DynamicDataSourceFilter.java index 5782023..8a38ff1 100644 --- a/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/filters/DynamicDataSourceFilter.java +++ b/qiaoba-modules/qiaoba-module-tenant/src/main/java/com/qiaoba/module/tenant/filters/DynamicDataSourceFilter.java @@ -2,14 +2,17 @@ package com.qiaoba.module.tenant.filters; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; +import com.qiaoba.auth.properties.AuthConfigProperties; import com.qiaoba.common.base.constants.TenantConstant; 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.constants.DynamicDatasourceConstant; 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.enums.TenantStatusEnum; import com.qiaoba.module.tenant.service.SysTenantService; +import lombok.extern.slf4j.Slf4j; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; @@ -32,35 +35,50 @@ import java.util.Objects; */ @Component @Order(-10000) +@Slf4j public class DynamicDataSourceFilter extends OncePerRequestFilter { @Resource private SysTenantService sysTenantService; @Resource private DynamicDataSourceConfig dynamicDataSourceConfig; + @Resource + private AuthConfigProperties authConfigProperties; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String tenantId = request.getHeader(TenantConstant.HEADER_KEY_TENANT); - // 主库或没有tenantId - if (StrUtil.isBlank(tenantId) - || TenantConstant.DEFAULT_TENANT_ID.equals(tenantId) - || request.getRequestURI().startsWith("/tenant")) { + // 主系统 + if (TenantConstant.DEFAULT_TENANT_ID.equals(tenantId)) { dynamicDataSourceConfig.setDefaultSetting(); filterChain.doFilter(request, response); + after(); 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); + // 检查租户是否允许访问 if (checkTenantIsNotAllow(response, sysTenant)) { return; } + // 设置租户信息 before(sysTenant); filterChain.doFilter(request, response); after(); } private void before(SysTenant sysTenant) { + log.debug(StrUtil.format("设置租户信息, 租户ID: {},租户模式: {}", sysTenant.getTenantId(), sysTenant.getMode())); BaseContext.setTenantId(sysTenant.getTenantId()); BaseContext.setSchema(sysTenant.getMode().equals(SysTenant.SCHEMA_MODE)); // 数据源模式-设置第三方数据源 @@ -68,7 +86,7 @@ public class DynamicDataSourceFilter extends OncePerRequestFilter { //设置当前租户对应的数据源 BaseContext.setDataSource(DynamicDatasourceConstant.MASTER_PREFIX + sysTenant.getTenantId()); } - // 字段模式/Schema模式-数据源选择默认数据源 + // 字段模式 or Schema模式-数据源选择默认数据源 else { BaseContext.setDataSource(DynamicDatasourceConstant.MASTER_PREFIX + TenantConstant.DEFAULT_TENANT_ID); } @@ -77,6 +95,7 @@ public class DynamicDataSourceFilter extends OncePerRequestFilter { } private void after() { + log.debug("clear the BaseContext"); BaseContext.clearAllHolder(); } @@ -93,15 +112,22 @@ public class DynamicDataSourceFilter extends OncePerRequestFilter { return true; } - if (sysTenant.getStatus().equals(BaseEnum.ABNORMAL.getCode())) { + if (TenantStatusEnum.DISABLE.getStatus().equals(sysTenant.getStatus())) { // 封禁状态 ResponseUtil.errorAuth(response, 401, "租户已被封禁"); return true; } + if (TenantStatusEnum.EXPIRE.getStatus().equals(sysTenant.getStatus())) { + // 已过期 + ResponseUtil.errorAuth(response, 401, "租户已过期"); + return true; + } if (DateUtil.compare(sysTenant.getExpireTime(), new Date()) < 0) { // 已过期 ResponseUtil.errorAuth(response, 401, "租户已过期"); + // 更新租户状态为已过期 + sysTenantService.update(new SysTenant(sysTenant.getTenantId(), TenantStatusEnum.EXPIRE.getStatus())); return true; } return false;