Commit f0402f69e1328496fe2ade87354c8e9c87663fe0

Authored by YunaiV
1 parent 040899d8

fix:【framework 框架】修改配置会导致 TenantIgnore 注解的 controller 接口过滤失效,https://gitee.com/z…

…hijiantianya/yudao-cloud/issues/ICUQL9
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java
... ... @@ -44,8 +44,7 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
44 44 import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
45 45 import org.springframework.web.util.pattern.PathPattern;
46 46  
47   -import java.util.Map;
48   -import java.util.Objects;
  47 +import java.util.*;
49 48  
50 49 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
51 50  
... ... @@ -84,41 +83,13 @@ public class YudaoTenantAutoConfiguration {
84 83 // ========== WEB ==========
85 84  
86 85 @Bean
87   - public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter(TenantProperties tenantProperties) {
  86 + public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter() {
88 87 FilterRegistrationBean<TenantContextWebFilter> registrationBean = new FilterRegistrationBean<>();
89 88 registrationBean.setFilter(new TenantContextWebFilter());
90 89 registrationBean.setOrder(WebFilterOrderEnum.TENANT_CONTEXT_FILTER);
91   - addIgnoreUrls(tenantProperties);
92 90 return registrationBean;
93 91 }
94 92  
95   - /**
96   - * 如果 Controller 接口上,有 {@link TenantIgnore} 注解,那么添加到忽略的 URL 中
97   - *
98   - * @param tenantProperties 租户配置
99   - */
100   - private void addIgnoreUrls(TenantProperties tenantProperties) {
101   - // 获得接口对应的 HandlerMethod 集合
102   - RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping)
103   - applicationContext.getBean("requestMappingHandlerMapping");
104   - Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
105   - // 获得有 @TenantIgnore 注解的接口
106   - for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethodMap.entrySet()) {
107   - HandlerMethod handlerMethod = entry.getValue();
108   - if (!handlerMethod.hasMethodAnnotation(TenantIgnore.class)) {
109   - continue;
110   - }
111   - // 添加到忽略的 URL 中
112   - if (entry.getKey().getPatternsCondition() != null) {
113   - tenantProperties.getIgnoreUrls().addAll(entry.getKey().getPatternsCondition().getPatterns());
114   - }
115   - if (entry.getKey().getPathPatternsCondition() != null) {
116   - tenantProperties.getIgnoreUrls().addAll(
117   - convertList(entry.getKey().getPathPatternsCondition().getPatterns(), PathPattern::getPatternString));
118   - }
119   - }
120   - }
121   -
122 93 @Bean
123 94 public TenantVisitContextInterceptor tenantVisitContextInterceptor(TenantProperties tenantProperties,
124 95 SecurityFrameworkService securityFrameworkService) {
... ... @@ -146,12 +117,41 @@ public class YudaoTenantAutoConfiguration {
146 117 GlobalExceptionHandler globalExceptionHandler,
147 118 TenantFrameworkService tenantFrameworkService) {
148 119 FilterRegistrationBean<TenantSecurityWebFilter> registrationBean = new FilterRegistrationBean<>();
149   - registrationBean.setFilter(new TenantSecurityWebFilter(tenantProperties, webProperties,
  120 + registrationBean.setFilter(new TenantSecurityWebFilter(webProperties, tenantProperties, getTenantIgnoreUrls(),
150 121 globalExceptionHandler, tenantFrameworkService));
151 122 registrationBean.setOrder(WebFilterOrderEnum.TENANT_SECURITY_FILTER);
152 123 return registrationBean;
153 124 }
154 125  
  126 + /**
  127 + * 如果 Controller 接口上,有 {@link TenantIgnore} 注解,则添加到忽略租户的 URL 集合中
  128 + *
  129 + * @return 忽略租户的 URL 集合
  130 + */
  131 + private Set<String> getTenantIgnoreUrls() {
  132 + Set<String> ignoreUrls = new HashSet<>();
  133 + // 获得接口对应的 HandlerMethod 集合
  134 + RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping)
  135 + applicationContext.getBean("requestMappingHandlerMapping");
  136 + Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
  137 + // 获得有 @TenantIgnore 注解的接口
  138 + for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethodMap.entrySet()) {
  139 + HandlerMethod handlerMethod = entry.getValue();
  140 + if (!handlerMethod.hasMethodAnnotation(TenantIgnore.class)) {
  141 + continue;
  142 + }
  143 + // 添加到忽略的 URL 中
  144 + if (entry.getKey().getPatternsCondition() != null) {
  145 + ignoreUrls.addAll(entry.getKey().getPatternsCondition().getPatterns());
  146 + }
  147 + if (entry.getKey().getPathPatternsCondition() != null) {
  148 + ignoreUrls.addAll(
  149 + convertList(entry.getKey().getPathPatternsCondition().getPatterns(), PathPattern::getPatternString));
  150 + }
  151 + }
  152 + return ignoreUrls;
  153 + }
  154 +
155 155 // ========== MQ ==========
156 156  
157 157 @Bean
... ...
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/security/TenantSecurityWebFilter.java
... ... @@ -12,15 +12,16 @@ import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
12 12 import cn.iocoder.yudao.framework.web.config.WebProperties;
13 13 import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter;
14 14 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
15   -import lombok.extern.slf4j.Slf4j;
16   -import org.springframework.util.AntPathMatcher;
17   -
18 15 import jakarta.servlet.FilterChain;
19 16 import jakarta.servlet.ServletException;
20 17 import jakarta.servlet.http.HttpServletRequest;
21 18 import jakarta.servlet.http.HttpServletResponse;
  19 +import lombok.extern.slf4j.Slf4j;
  20 +import org.springframework.util.AntPathMatcher;
  21 +
22 22 import java.io.IOException;
23 23 import java.util.Objects;
  24 +import java.util.Set;
24 25  
25 26 /**
26 27 * 多租户 Security Web 过滤器
... ... @@ -35,17 +36,26 @@ public class TenantSecurityWebFilter extends ApiRequestFilter {
35 36  
36 37 private final TenantProperties tenantProperties;
37 38  
  39 + /**
  40 + * 允许忽略租户的 URL 列表
  41 + *
  42 + * 目的:解决 <a href="https://gitee.com/zhijiantianya/yudao-cloud/issues/ICUQL9">修改配置会导致 @TenantIgnore Controller 接口过滤失效</>
  43 + */
  44 + private final Set<String> ignoreUrls;
  45 +
38 46 private final AntPathMatcher pathMatcher;
39 47  
40 48 private final GlobalExceptionHandler globalExceptionHandler;
41 49 private final TenantFrameworkService tenantFrameworkService;
42 50  
43   - public TenantSecurityWebFilter(TenantProperties tenantProperties,
44   - WebProperties webProperties,
  51 + public TenantSecurityWebFilter(WebProperties webProperties,
  52 + TenantProperties tenantProperties,
  53 + Set<String> ignoreUrls,
45 54 GlobalExceptionHandler globalExceptionHandler,
46 55 TenantFrameworkService tenantFrameworkService) {
47 56 super(webProperties);
48 57 this.tenantProperties = tenantProperties;
  58 + this.ignoreUrls = ignoreUrls;
49 59 this.pathMatcher = new AntPathMatcher();
50 60 this.globalExceptionHandler = globalExceptionHandler;
51 61 this.tenantFrameworkService = tenantFrameworkService;
... ... @@ -103,7 +113,8 @@ public class TenantSecurityWebFilter extends ApiRequestFilter {
103 113 private boolean isIgnoreUrl(HttpServletRequest request) {
104 114 String apiUri = request.getRequestURI().substring(request.getContextPath().length());
105 115 // 快速匹配,保证性能
106   - if (CollUtil.contains(tenantProperties.getIgnoreUrls(), apiUri)) {
  116 + if (CollUtil.contains(tenantProperties.getIgnoreUrls(), apiUri)
  117 + || CollUtil.contains(ignoreUrls, apiUri)) {
107 118 return true;
108 119 }
109 120 // 逐个 Ant 路径匹配
... ... @@ -112,6 +123,11 @@ public class TenantSecurityWebFilter extends ApiRequestFilter {
112 123 return true;
113 124 }
114 125 }
  126 + for (String url : ignoreUrls) {
  127 + if (pathMatcher.match(url, apiUri)) {
  128 + return true;
  129 + }
  130 + }
115 131 return false;
116 132 }
117 133  
... ...