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> 执行了哪些操作?
posted @ 2017-10-18 16:09  图生  阅读(1732)  评论(0)    收藏  举报