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,8 +44,7 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfo; | ||
| 44 | import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; | 44 | import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; |
| 45 | import org.springframework.web.util.pattern.PathPattern; | 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 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | 49 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| 51 | 50 | ||
| @@ -84,41 +83,13 @@ public class YudaoTenantAutoConfiguration { | @@ -84,41 +83,13 @@ public class YudaoTenantAutoConfiguration { | ||
| 84 | // ========== WEB ========== | 83 | // ========== WEB ========== |
| 85 | 84 | ||
| 86 | @Bean | 85 | @Bean |
| 87 | - public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter(TenantProperties tenantProperties) { | 86 | + public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter() { |
| 88 | FilterRegistrationBean<TenantContextWebFilter> registrationBean = new FilterRegistrationBean<>(); | 87 | FilterRegistrationBean<TenantContextWebFilter> registrationBean = new FilterRegistrationBean<>(); |
| 89 | registrationBean.setFilter(new TenantContextWebFilter()); | 88 | registrationBean.setFilter(new TenantContextWebFilter()); |
| 90 | registrationBean.setOrder(WebFilterOrderEnum.TENANT_CONTEXT_FILTER); | 89 | registrationBean.setOrder(WebFilterOrderEnum.TENANT_CONTEXT_FILTER); |
| 91 | - addIgnoreUrls(tenantProperties); | ||
| 92 | return registrationBean; | 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 | @Bean | 93 | @Bean |
| 123 | public TenantVisitContextInterceptor tenantVisitContextInterceptor(TenantProperties tenantProperties, | 94 | public TenantVisitContextInterceptor tenantVisitContextInterceptor(TenantProperties tenantProperties, |
| 124 | SecurityFrameworkService securityFrameworkService) { | 95 | SecurityFrameworkService securityFrameworkService) { |
| @@ -146,12 +117,41 @@ public class YudaoTenantAutoConfiguration { | @@ -146,12 +117,41 @@ public class YudaoTenantAutoConfiguration { | ||
| 146 | GlobalExceptionHandler globalExceptionHandler, | 117 | GlobalExceptionHandler globalExceptionHandler, |
| 147 | TenantFrameworkService tenantFrameworkService) { | 118 | TenantFrameworkService tenantFrameworkService) { |
| 148 | FilterRegistrationBean<TenantSecurityWebFilter> registrationBean = new FilterRegistrationBean<>(); | 119 | FilterRegistrationBean<TenantSecurityWebFilter> registrationBean = new FilterRegistrationBean<>(); |
| 149 | - registrationBean.setFilter(new TenantSecurityWebFilter(tenantProperties, webProperties, | 120 | + registrationBean.setFilter(new TenantSecurityWebFilter(webProperties, tenantProperties, getTenantIgnoreUrls(), |
| 150 | globalExceptionHandler, tenantFrameworkService)); | 121 | globalExceptionHandler, tenantFrameworkService)); |
| 151 | registrationBean.setOrder(WebFilterOrderEnum.TENANT_SECURITY_FILTER); | 122 | registrationBean.setOrder(WebFilterOrderEnum.TENANT_SECURITY_FILTER); |
| 152 | return registrationBean; | 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 | // ========== MQ ========== | 155 | // ========== MQ ========== |
| 156 | 156 | ||
| 157 | @Bean | 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,15 +12,16 @@ import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; | ||
| 12 | import cn.iocoder.yudao.framework.web.config.WebProperties; | 12 | import cn.iocoder.yudao.framework.web.config.WebProperties; |
| 13 | import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter; | 13 | import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter; |
| 14 | import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; | 14 | import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; |
| 15 | -import lombok.extern.slf4j.Slf4j; | ||
| 16 | -import org.springframework.util.AntPathMatcher; | ||
| 17 | - | ||
| 18 | import jakarta.servlet.FilterChain; | 15 | import jakarta.servlet.FilterChain; |
| 19 | import jakarta.servlet.ServletException; | 16 | import jakarta.servlet.ServletException; |
| 20 | import jakarta.servlet.http.HttpServletRequest; | 17 | import jakarta.servlet.http.HttpServletRequest; |
| 21 | import jakarta.servlet.http.HttpServletResponse; | 18 | import jakarta.servlet.http.HttpServletResponse; |
| 19 | +import lombok.extern.slf4j.Slf4j; | ||
| 20 | +import org.springframework.util.AntPathMatcher; | ||
| 21 | + | ||
| 22 | import java.io.IOException; | 22 | import java.io.IOException; |
| 23 | import java.util.Objects; | 23 | import java.util.Objects; |
| 24 | +import java.util.Set; | ||
| 24 | 25 | ||
| 25 | /** | 26 | /** |
| 26 | * 多租户 Security Web 过滤器 | 27 | * 多租户 Security Web 过滤器 |
| @@ -35,17 +36,26 @@ public class TenantSecurityWebFilter extends ApiRequestFilter { | @@ -35,17 +36,26 @@ public class TenantSecurityWebFilter extends ApiRequestFilter { | ||
| 35 | 36 | ||
| 36 | private final TenantProperties tenantProperties; | 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 | private final AntPathMatcher pathMatcher; | 46 | private final AntPathMatcher pathMatcher; |
| 39 | 47 | ||
| 40 | private final GlobalExceptionHandler globalExceptionHandler; | 48 | private final GlobalExceptionHandler globalExceptionHandler; |
| 41 | private final TenantFrameworkService tenantFrameworkService; | 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 | GlobalExceptionHandler globalExceptionHandler, | 54 | GlobalExceptionHandler globalExceptionHandler, |
| 46 | TenantFrameworkService tenantFrameworkService) { | 55 | TenantFrameworkService tenantFrameworkService) { |
| 47 | super(webProperties); | 56 | super(webProperties); |
| 48 | this.tenantProperties = tenantProperties; | 57 | this.tenantProperties = tenantProperties; |
| 58 | + this.ignoreUrls = ignoreUrls; | ||
| 49 | this.pathMatcher = new AntPathMatcher(); | 59 | this.pathMatcher = new AntPathMatcher(); |
| 50 | this.globalExceptionHandler = globalExceptionHandler; | 60 | this.globalExceptionHandler = globalExceptionHandler; |
| 51 | this.tenantFrameworkService = tenantFrameworkService; | 61 | this.tenantFrameworkService = tenantFrameworkService; |
| @@ -103,7 +113,8 @@ public class TenantSecurityWebFilter extends ApiRequestFilter { | @@ -103,7 +113,8 @@ public class TenantSecurityWebFilter extends ApiRequestFilter { | ||
| 103 | private boolean isIgnoreUrl(HttpServletRequest request) { | 113 | private boolean isIgnoreUrl(HttpServletRequest request) { |
| 104 | String apiUri = request.getRequestURI().substring(request.getContextPath().length()); | 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 | return true; | 118 | return true; |
| 108 | } | 119 | } |
| 109 | // 逐个 Ant 路径匹配 | 120 | // 逐个 Ant 路径匹配 |
| @@ -112,6 +123,11 @@ public class TenantSecurityWebFilter extends ApiRequestFilter { | @@ -112,6 +123,11 @@ public class TenantSecurityWebFilter extends ApiRequestFilter { | ||
| 112 | return true; | 123 | return true; |
| 113 | } | 124 | } |
| 114 | } | 125 | } |
| 126 | + for (String url : ignoreUrls) { | ||
| 127 | + if (pathMatcher.match(url, apiUri)) { | ||
| 128 | + return true; | ||
| 129 | + } | ||
| 130 | + } | ||
| 115 | return false; | 131 | return false; |
| 116 | } | 132 | } |
| 117 | 133 |