最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring mvc url匹配禁用后綴訪問操作

 更新時(shí)間:2021年07月19日 08:47:12   作者:Felix Zh  
這篇文章主要介紹了spring mvc url匹配禁用后綴訪問操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家

spring mvc url匹配禁用后綴訪問

在spring mvc中默認(rèn) 訪問url 加任意后綴名都能訪問

比如:你想訪問 /login ,但是通過 /login.do /login.action /login.json 都能訪問

通常來說可能沒有影響,但對(duì)于權(quán)限控制,這就嚴(yán)重了。

權(quán)限控制通常有兩種思路:

1)弱權(quán)限控制

允許所有url通過,僅對(duì)個(gè)別重要的url做權(quán)限控制。此種方式比較簡(jiǎn)單,不需要對(duì)所有url資源進(jìn)行配置,只配置重要的資源。

2)強(qiáng)權(quán)限控制

默認(rèn)禁止所有url請(qǐng)求通過,僅開放授權(quán)的資源。此種方式對(duì)所有的url資源進(jìn)行控制。在系統(tǒng)種需要整理所有的請(qǐng)求,或者某一目錄下所有的url資源。這種方式安全控制比較嚴(yán)格,操作麻煩,但相對(duì)安全。

如果用第二種方式,則上面spring mvc的訪問策略對(duì)安全沒有影響。

但如果用第一種安全策略,則會(huì)有很大的安全風(fēng)險(xiǎn)。

例如:我們控制了/login 的訪問,但是我們默認(rèn)除/login的資源不受權(quán)限控制約束,那么攻擊者就可以用 /login.do /login.xxx 來訪問我們的資源。

在spring 3.1之后,url找對(duì)應(yīng)方法的處理步驟,第一步,直接調(diào)用RequestMappingHandlerMapping查找到相應(yīng)的處理方法,第二步,調(diào)用RequestMappingHandlerAdapter進(jìn)行處理

我們?cè)赗equestMappingHandlerMapping中可以看到

/**
 * Whether to use suffix pattern match for registered file extensions only
 * when matching patterns to requests.
 * <p>If enabled, a controller method mapped to "/users" also matches to
 * "/users.json" assuming ".json" is a file extension registered with the
 * provided {@link #setContentNegotiationManager(ContentNegotiationManager)
 * contentNegotiationManager}. This can be useful for allowing only specific
 * URL extensions to be used as well as in cases where a "." in the URL path
 * can lead to ambiguous interpretation of path variable content, (e.g. given
 * "/users/{user}" and incoming URLs such as "/users/john.j.joe" and
 * "/users/john.j.joe.json").
 * <p>If enabled, this flag also enables
 * {@link #setUseSuffixPatternMatch(boolean) useSuffixPatternMatch}. The
 * default value is {@code false}.
 */
public void setUseRegisteredSuffixPatternMatch(boolean useRegisteredSuffixPatternMatch) {
   this.useRegisteredSuffixPatternMatch = useRegisteredSuffixPatternMatch;
   this.useSuffixPatternMatch = (useRegisteredSuffixPatternMatch || this.useSuffixPatternMatch);
}

那么如何來配置呢?

  <mvc:annotation-driven>
    <mvc:path-matching suffix-pattern="false" />
  </mvc:annotation-driven>

在匹配模式時(shí)是否使用后綴模式匹配,默認(rèn)值為true。這樣你想訪問 /login ,通過 /login.* 就不能訪問了。

spring mvc 之 請(qǐng)求url 帶后綴的情況

RequestMappingInfoHandlerMapping 在處理http請(qǐng)求的時(shí)候, 如果 請(qǐng)求url 有后綴,如果找不到精確匹配的那個(gè)@RequestMapping方法。

那么,就把后綴去掉,然后.* 去匹配,這樣,一般都可以匹配。 比如有一個(gè)@RequestMapping("/rest"), 那么精確匹配的情況下, 只會(huì)匹配/rest請(qǐng)求。

但如果我前端發(fā)來一個(gè) /rest.abcdef 這樣的請(qǐng)求, 又沒有配置 @RequestMapping("/rest.abcdef") 這樣映射的情況下, 那么@RequestMapping("/rest") 就會(huì)生效。

原理呢?處理鏈?zhǔn)沁@樣的:

at org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getMatchingPattern(PatternsRequestCondition.java:254)
at org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getMatchingPatterns(PatternsRequestCondition.java:230)
at org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getMatchingCondition(PatternsRequestCondition.java:210)
at org.springframework.web.servlet.mvc.method.RequestMappingInfo.getMatchingCondition(RequestMappingInfo.java:214)
at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getMatchingMapping(RequestMappingInfoHandlerMapping.java:79)
at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.getMatchingMapping(RequestMappingInfoHandlerMapping.java:56)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.addMatchingMappings(AbstractHandlerMethodMapping.java:358)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:328)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:299)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:57)
at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:299)
at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1104)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:916)

關(guān)鍵是PatternsRequestCondition, 具體來說是這個(gè)方法:

AbstractHandlerMethodMapping 的getHandlerInternal:
    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
        String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request);
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Looking up handler method for path " + lookupPath);
        }
        HandlerMethod handlerMethod = this.lookupHandlerMethod(lookupPath, request);// 這里是關(guān)鍵,它去尋找,找到了就找到了,找不到就不會(huì)再去尋找了
        if (this.logger.isDebugEnabled()) {
            if (handlerMethod != null) {
                this.logger.debug("Returning handler method [" + handlerMethod + "]");
            } else {
                this.logger.debug("Did not find handler method for [" + lookupPath + "]");
            }
        }
        return handlerMethod != null ? handlerMethod.createWithResolvedBean() : null;
    }
    
    
    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
        List<AbstractHandlerMethodMapping<T>.Match> matches = new ArrayList();
        List<T> directPathMatches = (List)this.urlMap.get(lookupPath); // directPathMatches, 直接匹配, 也可以說是 精確匹配
        if (directPathMatches != null) {
            this.addMatchingMappings(directPathMatches, matches, request);// 如果能夠精確匹配, 就會(huì)進(jìn)來這里
        }
        if (matches.isEmpty()) {
            this.addMatchingMappings(this.handlerMethods.keySet(), matches, request);// 如果無法精確匹配, 就會(huì)進(jìn)來這里
        }
        if (!matches.isEmpty()) {
            Comparator<AbstractHandlerMethodMapping<T>.Match> comparator = new AbstractHandlerMethodMapping.MatchComparator(this.getMappingComparator(request));
            Collections.sort(matches, comparator);
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches);
            }
            AbstractHandlerMethodMapping<T>.Match bestMatch = (AbstractHandlerMethodMapping.Match)matches.get(0);
            if (matches.size() > 1) {
                AbstractHandlerMethodMapping<T>.Match secondBestMatch = (AbstractHandlerMethodMapping.Match)matches.get(1);
                if (comparator.compare(bestMatch, secondBestMatch) == 0) {
                    Method m1 = bestMatch.handlerMethod.getMethod();
                    Method m2 = secondBestMatch.handlerMethod.getMethod();
                    throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" + request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
                }
            }
            this.handleMatch(bestMatch.mapping, lookupPath, request);
            return bestMatch.handlerMethod;
        } else {
            return this.handleNoMatch(this.handlerMethods.keySet(), lookupPath, request);
        }
    }
    
    public List<String> getMatchingPatterns(String lookupPath) {
        List<String> matches = new ArrayList();
        Iterator var3 = this.patterns.iterator();
        while(var3.hasNext()) {
            String pattern = (String)var3.next(); // pattern 是 @RequestMapping 提供的映射
            String match = this.getMatchingPattern(pattern, lookupPath); //  lookupPath + .*  后能夠匹配pattern, 那么就不為空
            if (match != null) {
                matches.add(match);// 對(duì)于有后綴的情況, .* 后
            }
        }
        Collections.sort(matches, this.pathMatcher.getPatternComparator(lookupPath));
        return matches;
    }
    最關(guān)鍵是這里 getMatchingPatterns :
    private String getMatchingPattern(String pattern, String lookupPath) {
        if (pattern.equals(lookupPath)) {
            return pattern;
        } else {
            if (this.useSuffixPatternMatch) {
                if (!this.fileExtensions.isEmpty() && lookupPath.indexOf(46) != -1) {
                    Iterator var5 = this.fileExtensions.iterator();
                    while(var5.hasNext()) {
                        String extension = (String)var5.next();
                        if (this.pathMatcher.match(pattern + extension, lookupPath)) {
                            return pattern + extension;
                        }
                    }
                } else {
                    boolean hasSuffix = pattern.indexOf(46) != -1;
                    if (!hasSuffix && this.pathMatcher.match(pattern + ".*", lookupPath)) {
                        return pattern + ".*"; // 關(guān)鍵是這里
                    }
                }
            }
            if (this.pathMatcher.match(pattern, lookupPath)) {
                return pattern;
            } else {
                return this.useTrailingSlashMatch && !pattern.endsWith("/") && this.pathMatcher.match(pattern + "/", lookupPath) ? pattern + "/" : null;
            }
        }
    }

而對(duì)于AbstractUrlHandlerMapping ,匹配不上就是匹配不上, 不會(huì)進(jìn)行 +.* 后在匹配。

關(guān)鍵方法是這個(gè):

protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
        Object handler = this.handlerMap.get(urlPath);
        if (handler != null) {
            if (handler instanceof String) {
                String handlerName = (String)handler;
                handler = this.getApplicationContext().getBean(handlerName);
            }
            this.validateHandler(handler, request);
            return this.buildPathExposingHandler(handler, urlPath, urlPath, (Map)null);
        } else {
            List<String> matchingPatterns = new ArrayList();
            Iterator var5 = this.handlerMap.keySet().iterator();
            while(var5.hasNext()) {
                String registeredPattern = (String)var5.next();
                if (this.getPathMatcher().match(registeredPattern, urlPath)) {
                    matchingPatterns.add(registeredPattern);
                }
            }
            String bestPatternMatch = null;
            Comparator<String> patternComparator = this.getPathMatcher().getPatternComparator(urlPath);
            if (!matchingPatterns.isEmpty()) {
                Collections.sort(matchingPatterns, patternComparator);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
                }
                bestPatternMatch = (String)matchingPatterns.get(0);
            }
            if (bestPatternMatch != null) {
                handler = this.handlerMap.get(bestPatternMatch);
                String pathWithinMapping;
                if (handler instanceof String) {
                    pathWithinMapping = (String)handler;
                    handler = this.getApplicationContext().getBean(pathWithinMapping);
                }
                this.validateHandler(handler, request);
                pathWithinMapping = this.getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);
                Map<String, String> uriTemplateVariables = new LinkedHashMap();
                Iterator var9 = matchingPatterns.iterator();
                while(var9.hasNext()) {
                    String matchingPattern = (String)var9.next();
                    if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {
                        Map<String, String> vars = this.getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
                        Map<String, String> decodedVars = this.getUrlPathHelper().decodePathVariables(request, vars);
                        uriTemplateVariables.putAll(decodedVars);
                    }
                }
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
                }
                return this.buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);
            } else {
                return null;
            }
        }
    }

當(dāng)然, 或許我們可以設(shè)置自定義的PathMatcher ,從而到達(dá)目的。 默認(rèn)的 是AntPathMatcher 。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 快速解決?IDEA?報(bào)錯(cuò):?“java?找不到符號(hào)“(“cannot?find?symbol“)

    快速解決?IDEA?報(bào)錯(cuò):?“java?找不到符號(hào)“(“cannot?find?symbol“)

    文章詳細(xì)講解了在IntelliJIDEA中解決“找不到符號(hào)”錯(cuò)誤的方法,包括檢查導(dǎo)入語(yǔ)句、拼寫錯(cuò)誤、類路徑設(shè)置、文件編譯狀態(tài)、JDK配置以及IDE配置問題,通過具體示例代碼,展示了如何從錯(cuò)誤代碼到解決步驟,感興趣的朋友一起看看吧
    2025-03-03
  • 解析Java Class 文件過程

    解析Java Class 文件過程

    class文件全名稱為Java class文件,主要在平臺(tái)無關(guān)性和網(wǎng)絡(luò)移動(dòng)性方面使Java更適合網(wǎng)絡(luò)。它在平臺(tái)無關(guān)性方面的任務(wù)是:為Java程序提供獨(dú)立于底層主機(jī)平臺(tái)的二進(jìn)制形式的服務(wù)。下面我們來詳細(xì)解讀下它吧
    2019-05-05
  • java導(dǎo)出生成csv文件的方法

    java導(dǎo)出生成csv文件的方法

    這篇文章主要為大家詳細(xì)介紹了java導(dǎo)出生成csv文件的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • SpringBoot集成P6Spy實(shí)現(xiàn)SQL日志的記錄詳解

    SpringBoot集成P6Spy實(shí)現(xiàn)SQL日志的記錄詳解

    P6Spy是一個(gè)框架,它可以無縫地?cái)r截和記錄數(shù)據(jù)庫(kù)活動(dòng),而無需更改現(xiàn)有應(yīng)用程序的代碼。一般我們使用的比較多的是使用p6spy打印我們最后執(zhí)行的sql語(yǔ)句
    2022-11-11
  • java生成圖片進(jìn)行套打功能

    java生成圖片進(jìn)行套打功能

    這篇文章主要為大家詳細(xì)介紹了java生成圖片進(jìn)行套打功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • SpringBoot集成mybatis實(shí)例

    SpringBoot集成mybatis實(shí)例

    本篇文章主要介紹了SpringBoot集成mybatis實(shí)例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-04-04
  • 長(zhǎng)度最小的子數(shù)組題目詳解(Java版)

    長(zhǎng)度最小的子數(shù)組題目詳解(Java版)

    這篇文章主要給大家介紹了關(guān)于長(zhǎng)度最小的子數(shù)組(Java版)的相關(guān)資料,這到題來自力扣,通過學(xué)習(xí)本文對(duì)大家理解這道題目有很大的幫助,需要的朋友可以參考下
    2023-12-12
  • 詳解MyBatis的XML實(shí)現(xiàn)方法(附帶注解方式實(shí)現(xiàn))

    詳解MyBatis的XML實(shí)現(xiàn)方法(附帶注解方式實(shí)現(xiàn))

    這篇文章主要詳細(xì)介紹了MyBatis的XML實(shí)現(xiàn)方法(附帶注解方式實(shí)現(xiàn)),文中通過代碼示例給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-05-05
  • Java并發(fā)編程之ReentrantLock可重入鎖的實(shí)例代碼

    Java并發(fā)編程之ReentrantLock可重入鎖的實(shí)例代碼

    這篇文章主要介紹了Java并發(fā)編程之ReentrantLock可重入鎖的實(shí)例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • 一文教會(huì)你cmd命令運(yùn)行java程序

    一文教會(huì)你cmd命令運(yùn)行java程序

    這篇文章主要給大家介紹了關(guān)于如何使用cmd命令運(yùn)行java程序的相關(guān)資料,這是一個(gè)非常有用的技能,特別是當(dāng)您需要在沒有集成開發(fā)環(huán)境(IDE)的情況下編寫和運(yùn)行Java代碼時(shí),需要的朋友可以參考下<BR>
    2024-06-06

最新評(píng)論

深水埗区| 闻喜县| 三亚市| 伊川县| 儋州市| 金平| 崇信县| 阿拉善左旗| 兰州市| 黄龙县| 项城市| 自治县| 即墨市| SHOW| 安化县| 庐江县| 阳泉市| 广丰县| 民丰县| 阜城县| 丰城市| 麻江县| 彭山县| 萨迦县| 大港区| 武定县| 台湾省| 沙洋县| 林周县| 新密市| 太湖县| 福建省| 辽阳县| 洱源县| 光泽县| 昆山市| 临桂县| 沂南县| 汾阳市| 社会| 自贡市|