Browse Source

租户处理

yq 2 years ago
parent
commit
04c73759e4

+ 17 - 4
usky-common/usky-common-tenant/pom.xml

@@ -15,14 +15,27 @@
     <dependencies>
 
         <dependency>
-            <groupId>com.usky</groupId>
-            <artifactId>usky-common-mybatis</artifactId>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
         </dependency>
 
         <dependency>
-            <groupId>com.usky</groupId>
-            <artifactId>usky-common-security</artifactId>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
         </dependency>
 
+
+        <!-- Java Servlet -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+        </dependency>
+
+
     </dependencies>
 </project>

+ 2 - 2
usky-common/usky-common-tenant/src/main/java/com/usky/common/tenant/config/TenantProperties.java

@@ -10,14 +10,14 @@ import java.util.Set;
  *
  * @author yq
  */
-@ConfigurationProperties(prefix = "usky.tenant")
+@ConfigurationProperties(prefix = "tenant")
 @Data
 public class TenantProperties {
 
     /**
      * 租户是否开启
      */
-    private static final Boolean ENABLE_DEFAULT = true;
+    private static final Boolean ENABLE_DEFAULT = false;
 
     /**
      * 是否开启

+ 1 - 20
usky-common/usky-common-tenant/src/main/java/com/usky/common/tenant/config/UskyTenantAutoConfiguration.java

@@ -6,11 +6,7 @@ import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
 import com.usky.common.tenant.core.aop.TenantIgnoreAspect;
 import com.usky.common.tenant.core.db.TenantDatabaseInterceptor;
-import com.usky.common.tenant.core.security.TenantSecurityWebFilter;
-import com.usky.common.tenant.core.service.TenantFrameworkService;
-import com.usky.common.tenant.core.service.TenantFrameworkServiceImpl;
 import com.usky.common.tenant.core.web.TenantContextWebFilter;
-import com.usky.system.RemoteTenantService;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
@@ -21,14 +17,10 @@ import java.util.ArrayList;
 import java.util.List;
 
 @Configuration
-@ConditionalOnProperty(prefix = "usky.tenant", value = "enable", matchIfMissing = true) // 允许使用 yudao.tenant.enable=false 禁用多租户
+@ConditionalOnProperty(prefix = "tenant", value = "enable", matchIfMissing = true) // 允许使用 yudao.tenant.enable=false 禁用多租户
 @EnableConfigurationProperties(TenantProperties.class)
 public class UskyTenantAutoConfiguration {
 
-    @Bean
-    public TenantFrameworkService tenantFrameworkService(RemoteTenantService remoteTenantService) {
-        return new TenantFrameworkServiceImpl(remoteTenantService);
-    }
 
     // ========== AOP ==========
 
@@ -62,15 +54,4 @@ public class UskyTenantAutoConfiguration {
         return registrationBean;
     }
 
-    // ========== Security ==========
-
-    @Bean
-    public FilterRegistrationBean<TenantSecurityWebFilter> tenantSecurityWebFilter(TenantProperties tenantProperties,
-                                                                                   TenantFrameworkService tenantFrameworkService) {
-        FilterRegistrationBean<TenantSecurityWebFilter> registrationBean = new FilterRegistrationBean<>();
-        registrationBean.setFilter(new TenantSecurityWebFilter(tenantProperties, tenantFrameworkService));
-        registrationBean.setOrder(-99);
-        return registrationBean;
-    }
-
 }

+ 2 - 4
usky-common/usky-common-tenant/src/main/java/com/usky/common/tenant/core/context/TenantContextHolder.java

@@ -1,7 +1,5 @@
 package com.usky.common.tenant.core.context;
 
-import com.alibaba.ttl.TransmittableThreadLocal;
-
 /**
  * 多租户上下文 Holder
  *
@@ -12,12 +10,12 @@ public class TenantContextHolder {
     /**
      * 当前租户编号
      */
-    private static final ThreadLocal<Integer> TENANT_ID = new TransmittableThreadLocal<>();
+    private static final ThreadLocal<Integer> TENANT_ID = new ThreadLocal<>();
 
     /**
      * 是否忽略租户
      */
-    private static final ThreadLocal<Boolean> IGNORE = new TransmittableThreadLocal<>();
+    private static final ThreadLocal<Boolean> IGNORE = new ThreadLocal<>();
 
     /**
      * 获得租户编号。

+ 1 - 2
usky-common/usky-common-tenant/src/main/java/com/usky/common/tenant/core/db/TenantDatabaseInterceptor.java

@@ -1,6 +1,5 @@
 package com.usky.common.tenant.core.db;
 
-import cn.hutool.core.collection.CollUtil;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
 import com.usky.common.tenant.config.TenantProperties;
@@ -44,7 +43,7 @@ public class TenantDatabaseInterceptor implements TenantLineHandler {
         // 情况一,全局忽略多租户
         // 情况二,忽略多租户的表
         return TenantContextHolder.isIgnore()
-            || CollUtil.contains(ignoreTables, tableName);
+            || ignoreTables.stream().anyMatch(s -> s.equals(tableName));
     }
 
 }

+ 0 - 114
usky-common/usky-common-tenant/src/main/java/com/usky/common/tenant/core/security/TenantSecurityWebFilter.java

@@ -1,114 +0,0 @@
-package com.usky.common.tenant.core.security;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.collection.CollectionUtil;
-import com.alibaba.fastjson.JSON;
-import com.usky.common.core.bean.ApiResult;
-import com.usky.common.core.exception.BusinessException;
-import com.usky.common.core.util.ServletUtils;
-import com.usky.common.security.utils.SecurityUtils;
-import com.usky.common.tenant.config.TenantProperties;
-import com.usky.common.tenant.core.context.TenantContextHolder;
-import com.usky.common.tenant.core.service.TenantFrameworkService;
-import com.usky.system.model.LoginUser;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.http.HttpStatus;
-import org.springframework.util.AntPathMatcher;
-import org.springframework.web.filter.OncePerRequestFilter;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.Objects;
-
-/**
- * 多租户 Security Web 过滤器
- * 1. 如果是登陆的用户,校验是否有权限访问该租户,避免越权问题。
- * 2. 如果请求未带租户的编号,检查是否是忽略的 URL,否则也不允许访问。
- * 3. 校验租户是合法,例如说被禁用、到期
- *
- * 校验用户访问的租户,是否是其所在的租户,
- *
- * @author yq
- */
-@Slf4j
-public class TenantSecurityWebFilter extends OncePerRequestFilter {
-
-    private final TenantProperties tenantProperties;
-
-    private final AntPathMatcher pathMatcher;
-
-    private final TenantFrameworkService tenantFrameworkService;
-
-    public TenantSecurityWebFilter(TenantProperties tenantProperties,
-                                   TenantFrameworkService tenantFrameworkService) {
-        this.tenantProperties = tenantProperties;
-        this.pathMatcher = new AntPathMatcher();
-        this.tenantFrameworkService = tenantFrameworkService;
-    }
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
-            throws ServletException, IOException {
-        Integer tenantId = TenantContextHolder.getTenantId();
-        // 1. 登陆的用户,校验是否有权限访问该租户,避免越权问题。
-        LoginUser user = SecurityUtils.getLoginUser();
-        if (user != null) {
-            // 如果获取不到租户编号,则尝试使用登陆用户的租户编号
-            if (tenantId == null) {
-                tenantId = user.getTenantId();
-                TenantContextHolder.setTenantId(tenantId);
-            // 如果传递了租户编号,则进行比对租户编号,避免越权问题
-            } else if (!Objects.equals(user.getTenantId(), TenantContextHolder.getTenantId())) {
-                String msg = "您无权访问该租户的数据";
-                ServletUtils.renderString(response, JSON.toJSONString(ApiResult.error(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), msg)));
-                return;
-            }
-        }
-
-        // 如果非允许忽略租户的 URL,则校验租户是否合法
-        if (!isIgnoreUrl(request)) {
-            // 2. 如果请求未带租户的编号,不允许访问。
-            if (tenantId == null) {
-                String msg = "租户的请求未传递,请进行排查";
-                ServletUtils.renderString(response, JSON.toJSONString(ApiResult.error(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), msg)));
-                return;
-            }
-            // 3. 校验租户是合法,例如说被禁用、到期
-            try {
-                tenantFrameworkService.validTenant(tenantId);
-            } catch (Throwable ex) {
-                BusinessException businessException = (BusinessException)ex.getCause();
-                String msg = businessException.getCustomMessage();
-                ServletUtils.renderString(response, JSON.toJSONString(ApiResult.error(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), msg)));
-                return;
-            }
-        } else { // 如果是允许忽略租户的 URL,若未传递租户编号,则默认忽略租户编号,避免报错
-            if (tenantId == null) {
-                TenantContextHolder.setIgnore(true);
-            }
-        }
-
-        // 继续过滤
-        chain.doFilter(request, response);
-    }
-
-    private boolean isIgnoreUrl(HttpServletRequest request) {
-        if (CollectionUtil.isNotEmpty(tenantProperties.getIgnoreUrls())){
-            // 快速匹配,保证性能
-            if (CollUtil.contains(tenantProperties.getIgnoreUrls(), request.getRequestURI())) {
-                return true;
-            }
-            // 逐个 Ant 路径匹配
-            for (String url : tenantProperties.getIgnoreUrls()) {
-                if (pathMatcher.match(url, request.getRequestURI())) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-}

+ 0 - 26
usky-common/usky-common-tenant/src/main/java/com/usky/common/tenant/core/service/TenantFrameworkService.java

@@ -1,26 +0,0 @@
-package com.usky.common.tenant.core.service;
-
-import java.util.List;
-
-/**
- * Tenant 框架 Service 接口,定义获取租户信息
- *
- * @author yq
- */
-public interface TenantFrameworkService {
-
-    /**
-     * 获得所有租户
-     *
-     * @return 租户编号数组
-     */
-    List<Integer> getTenantIds();
-
-    /**
-     * 校验租户是否合法
-     *
-     * @param id 租户编号
-     */
-    Boolean validTenant(Integer id);
-
-}

+ 0 - 61
usky-common/usky-common-tenant/src/main/java/com/usky/common/tenant/core/service/TenantFrameworkServiceImpl.java

@@ -1,61 +0,0 @@
-package com.usky.common.tenant.core.service;
-
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.usky.common.core.util.CacheUtils;
-import com.usky.system.RemoteTenantService;
-import lombok.RequiredArgsConstructor;
-import lombok.SneakyThrows;
-
-import java.time.Duration;
-import java.util.List;
-
-/**
- * Tenant 框架 Service 实现类
- *
- * @author yq
- */
-@RequiredArgsConstructor
-public class TenantFrameworkServiceImpl implements TenantFrameworkService {
-
-
-    private final RemoteTenantService remoteTenantService;
-
-    /**
-     * 针对 {@link #getTenantIds()} 的缓存
-     */
-    private final LoadingCache<Object, List<Integer>> getTenantIdsCache = CacheUtils.buildAsyncReloadingCache(
-            Duration.ofMinutes(1L), // 过期时间 1 分钟
-            new CacheLoader<Object, List<Integer>>() {
-                @Override
-                public List<Integer> load(Object key) {
-                    return remoteTenantService.getTenantIds();
-                }
-            });
-
-    /**
-     * 针对校验结果的缓存
-      */
-    private final LoadingCache<Integer, Boolean> validTenantCache = CacheUtils.buildAsyncReloadingCache(
-            Duration.ofMinutes(1L), // 过期时间 1 分钟
-            new CacheLoader<Integer, Boolean>() {
-
-                @Override
-                public Boolean load(Integer id) {
-                    return remoteTenantService.validTenant(id);
-                }
-
-            });
-
-    @Override
-    @SneakyThrows
-    public List<Integer> getTenantIds() {
-        return getTenantIdsCache.get(Boolean.TRUE);
-    }
-
-    @Override
-    public Boolean validTenant(Integer id) {
-        return validTenantCache.getUnchecked(id);
-    }
-
-}

+ 0 - 36
usky-common/usky-common-tenant/src/main/java/com/usky/common/tenant/core/util/TenantUtils.java

@@ -1,36 +0,0 @@
-package com.usky.common.tenant.core.util;
-
-
-import com.usky.common.tenant.core.context.TenantContextHolder;
-
-/**
- * 多租户 Util
- *
- * @author yq
- */
-public class TenantUtils {
-
-    /**
-     * 使用指定租户,执行对应的逻辑
-     *
-     * 注意,如果当前是忽略租户的情况下,会被强制设置成不忽略租户
-     * 当然,执行完成后,还是会恢复回去
-     *
-     * @param tenantId 租户编号
-     * @param runnable 逻辑
-     */
-    public static void execute(Integer tenantId, Runnable runnable) {
-        Integer oldTenantId = TenantContextHolder.getTenantId();
-        Boolean oldIgnore = TenantContextHolder.isIgnore();
-        try {
-            TenantContextHolder.setTenantId(tenantId);
-            TenantContextHolder.setIgnore(false);
-            // 执行逻辑
-            runnable.run();
-        } finally {
-            TenantContextHolder.setTenantId(oldTenantId);
-            TenantContextHolder.setIgnore(oldIgnore);
-        }
-    }
-
-}

+ 5 - 1
usky-common/usky-common-tenant/src/main/java/com/usky/common/tenant/core/web/TenantContextWebFilter.java

@@ -1,7 +1,8 @@
 package com.usky.common.tenant.core.web;
 
-import com.usky.common.core.util.StringUtils;
+
 import com.usky.common.tenant.core.context.TenantContextHolder;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.web.filter.OncePerRequestFilter;
 
 import javax.servlet.FilterChain;
@@ -28,6 +29,9 @@ public class TenantContextWebFilter extends OncePerRequestFilter {
         if (tenantId != null) {
             TenantContextHolder.setTenantId(tenantId);
         }
+        if (tenantId == null) {
+            TenantContextHolder.setIgnore(true);
+        }
         try {
             chain.doFilter(request, response);
         } finally {