public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {
        FilterChainManager filterChainManager = getFilterChainManager();
        if (!filterChainManager.hasChains()) {
            return null;
        }

        final String requestURI = getPathWithinApplication(request);
        final String requestURINoTrailingSlash = removeTrailingSlash(requestURI);

        //the 'chain names' in this implementation are actually path patterns defined by the user.  We just use them
        //as the chain name for the FilterChainManager's requirements
        for (String pathPattern : filterChainManager.getChainNames()) {
            // If the path does match, then pass on to the subclass implementation for specific checks:
            if (pathMatches(pathPattern, requestURI)) {
                if (LOGGER.isTraceEnabled()) {
                    LOGGER.trace("Matched path pattern [{}] for requestURI [{}].  "
                            + "Utilizing corresponding filter chain...", pathPattern, Encode.forHtml(requestURI));
                }
                return filterChainManager.proxy(originalChain, pathPattern);
            } else {

                // in spring web, the requestURI "/resource/menus" ---- "resource/menus/" both can access the resource
                // but the pathPattern match "/resource/menus" can not match "resource/menus/"
                // user can use requestURI + "/" to simply bypassed chain filter, to bypassed shiro protect

                pathPattern = removeTrailingSlash(pathPattern);

                if (pathMatches(pathPattern, requestURINoTrailingSlash)) {
                    if (LOGGER.isTraceEnabled()) {
                        LOGGER.trace("Matched path pattern [{}] for requestURI [{}].  "
                                + "Utilizing corresponding filter chain...",
                                    pathPattern, Encode.forHtml(requestURINoTrailingSlash));
                    }
                    return filterChainManager.proxy(originalChain, pathPattern);
                }
            }
        }

        return null;
    }
Sets the {@code PatternMatcher} used when determining if an incoming request's path
matches a configured filter chain.  Unless overridden, the
default implementation is an {@link AntPathMatcher AntPathMatcher}.

@param pathMatcher the {@code PatternMatcher} used when determining if an incoming request's path
                   matches a configured filter chain.
web/src/main/java/org/apache/shiro/web/filter/mgt/PathMatchingFilterChainResolver.java