spring mvc url.xxx 禁用后缀访问
问题描述
原始url 路径: /login
/login.do 或者 /login.xxx 都可以访问到login接口
问题分析(从下向上看源码)
PatternsRequestCondition.getMatchingPattern(String, String) line: 254 PatternsRequestCondition.getMatchingPatterns(String) line: 230 PatternsRequestCondition.getMatchingCondition(HttpServletRequest) line: 210 RequestMappingInfo.getMatchingCondition(HttpServletRequest) line: 181 RequestMappingHandlerMapping(RequestMappingInfoHandlerMapping).getMatchingMapping(RequestMappingInfo, HttpServletRequest) line: 74 RequestMappingHandlerMapping(RequestMappingInfoHandlerMapping).getMatchingMapping(Object, HttpServletRequest) line: 56 RequestMappingHandlerMapping(AbstractHandlerMethodMapping<T>).addMatchingMappings(Collection<T>, List<AbstractHandlerMethodMapping<Matc>>, HttpServletRequest) line: 307 RequestMappingHandlerMapping(AbstractHandlerMethodMapping<T>).lookupHandlerMethod(String, HttpServletRequest) line: 277 RequestMappingHandlerMapping(AbstractHandlerMethodMapping<T>).getHandlerInternal(HttpServletRequest) line: 248 RequestMappingHandlerMapping(AbstractHandlerMethodMapping<T>).getHandlerInternal(HttpServletRequest) line: 57 RequestMappingHandlerMapping(AbstractHandlerMapping).getHandler(HttpServletRequest) line: 299 DispatcherServlet.getHandler(HttpServletRequest) line: 1098 DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse) line: 910 DispatcherServlet.doService(HttpServletRequest, HttpServletResponse) line: 870
咱们看第一条 PatternsRequestCondition.getMatchingPattern(String, String) line: 254
private String getMatchingPattern(String pattern, String lookupPath) { if (pattern.equals(lookupPath)) { return pattern; }
if (this.useSuffixPatternMatch) {//useSuffixPatternMatch是关键作用 默认为true if (!this.fileExtensions.isEmpty() && lookupPath.indexOf('.') != -1) { for (String extension : this.fileExtensions) { if (this.pathMatcher.match(pattern + extension, lookupPath)) { return pattern + extension; } } } else { boolean hasSuffix = pattern.indexOf('.') != -1; if (!hasSuffix && this.pathMatcher.match(pattern + ".*", lookupPath)) { return pattern + ".*"; //这里返回了login.* } } } if (this.pathMatcher.match(pattern, lookupPath)) { return pattern; } if (this.useTrailingSlashMatch) { if (!pattern.endsWith("/") && this.pathMatcher.match(pattern + "/", lookupPath)) { return pattern +"/"; } } return null; }
再追踪一下这个 useSuffixPatternMatch 从哪里设置
/** * Creates a new instance with the given URL patterns. * Each pattern that is not empty and does not start with "/" is pre-pended with "/". * @param patterns the URL patterns to use; if 0, the condition will match to every request. * @param urlPathHelper a {@link UrlPathHelper} for determining the lookup path for a request * @param pathMatcher a {@link PathMatcher} for pattern path matching * @param useSuffixPatternMatch whether to enable matching by suffix (".*") * @param useTrailingSlashMatch whether to match irrespective of a trailing slash * @param fileExtensions a list of file extensions to consider for path matching */ public PatternsRequestCondition(String[] patterns, UrlPathHelper urlPathHelper, PathMatcher pathMatcher, boolean useSuffixPatternMatch, boolean useTrailingSlashMatch, List<String> fileExtensions) { this(asList(patterns), urlPathHelper, pathMatcher, useSuffixPatternMatch, useTrailingSlashMatch, fileExtensions); }
RequestMappingHandlerMapping 的 createRequestMappingInfo
/** * Created a RequestMappingInfo from a RequestMapping annotation. */ protected RequestMappingInfo createRequestMappingInfo(RequestMapping annotation, RequestCondition<?> customCondition) { String[] patterns = resolveEmbeddedValuesInPatterns(annotation.value()); return new RequestMappingInfo( new PatternsRequestCondition(patterns, getUrlPathHelper(), getPathMatcher(), this.useSuffixPatternMatch, this.useTrailingSlashMatch, this.fileExtensions), new RequestMethodsRequestCondition(annotation.method()), new ParamsRequestCondition(annotation.params()), new HeadersRequestCondition(annotation.headers()), new ConsumesRequestCondition(annotation.consumes(), annotation.headers()), new ProducesRequestCondition(annotation.produces(), annotation.headers(), this.contentNegotiationManager), customCondition); }
RequestMappingHandlerMapping
/** * Whether to use suffix pattern match (".*") when matching patterns to * requests. If enabled a method mapped to "/users" also matches to "/users.*". * <p>The default value is {@code true}. * <p>Also see {@link #setUseRegisteredSuffixPatternMatch(boolean)} for * more fine-grained control over specific suffixes to allow. */ public void setUseSuffixPatternMatch(boolean useSuffixPatternMatch) { this.useSuffixPatternMatch = useSuffixPatternMatch; }
解决方案
<mvc:annotation-driven>
<!-- 是否在匹配模式时使用后缀模式匹配(" .*") 如果启用了映射到“/users”的方法,则匹配到“/users.*”。默认为true-->
<mvc:path-matching suffix-pattern="false" />
</mvc:annotation-driven>
遗留问题
<mvc:annotation-driven> 执行了哪些操作?

浙公网安备 33010602011771号