Commit f0402f69e1328496fe2ade87354c8e9c87663fe0
1 parent
040899d8
fix:【framework 框架】修改配置会导致 TenantIgnore 注解的 controller 接口过滤失效,https://gitee.com/z…
…hijiantianya/yudao-cloud/issues/ICUQL9
Showing
2 changed files
with
54 additions
and
38 deletions
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 | ... | ... |