@ -18,6 +18,8 @@ package org.springframework.security.config.annotation.web;
import java.util.ArrayList ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Arrays ;
import java.util.Collection ;
import java.util.LinkedHashMap ;
import java.util.List ;
import java.util.List ;
import java.util.Map ;
import java.util.Map ;
@ -194,18 +196,31 @@ public abstract class AbstractRequestMatcherRegistry<C> {
if ( servletContext = = null ) {
if ( servletContext = = null ) {
return requestMatchers ( RequestMatchers . antMatchersAsArray ( method , patterns ) ) ;
return requestMatchers ( RequestMatchers . antMatchersAsArray ( method , patterns ) ) ;
}
}
Map < String , ? extends ServletRegistration > registrations = servletContext . getServletRegistrations ( ) ;
Map < String , ? extends ServletRegistration > registrations = mappableServletRegistrations ( servletContext ) ;
if ( registrations = = null ) {
if ( registrations . isEmpty ( ) ) {
return requestMatchers ( RequestMatchers . antMatchersAsArray ( method , patterns ) ) ;
return requestMatchers ( RequestMatchers . antMatchersAsArray ( method , patterns ) ) ;
}
}
if ( ! hasDispatcherServlet ( registrations ) ) {
if ( ! hasDispatcherServlet ( registrations ) ) {
return requestMatchers ( RequestMatchers . antMatchersAsArray ( method , patterns ) ) ;
return requestMatchers ( RequestMatchers . antMatchersAsArray ( method , patterns ) ) ;
}
}
Assert . isTrue ( registrations . size ( ) = = 1 ,
if ( registrations . size ( ) > 1 ) {
"This method cannot decide whether these patterns are Spring MVC patterns or not. If this endpoint is a Spring MVC endpoint, please use requestMatchers(MvcRequestMatcher); otherwise, please use requestMatchers(AntPathRequestMatcher)." ) ;
String errorMessage = computeErrorMessage ( registrations . values ( ) ) ;
throw new IllegalArgumentException ( errorMessage ) ;
}
return requestMatchers ( createMvcMatchers ( method , patterns ) . toArray ( new RequestMatcher [ 0 ] ) ) ;
return requestMatchers ( createMvcMatchers ( method , patterns ) . toArray ( new RequestMatcher [ 0 ] ) ) ;
}
}
private Map < String , ? extends ServletRegistration > mappableServletRegistrations ( ServletContext servletContext ) {
Map < String , ServletRegistration > mappable = new LinkedHashMap < > ( ) ;
for ( Map . Entry < String , ? extends ServletRegistration > entry : servletContext . getServletRegistrations ( )
. entrySet ( ) ) {
if ( ! entry . getValue ( ) . getMappings ( ) . isEmpty ( ) ) {
mappable . put ( entry . getKey ( ) , entry . getValue ( ) ) ;
}
}
return mappable ;
}
private boolean hasDispatcherServlet ( Map < String , ? extends ServletRegistration > registrations ) {
private boolean hasDispatcherServlet ( Map < String , ? extends ServletRegistration > registrations ) {
if ( registrations = = null ) {
if ( registrations = = null ) {
return false ;
return false ;
@ -226,6 +241,19 @@ public abstract class AbstractRequestMatcherRegistry<C> {
return false ;
return false ;
}
}
private String computeErrorMessage ( Collection < ? extends ServletRegistration > registrations ) {
String template = "This method cannot decide whether these patterns are Spring MVC patterns or not. "
+ "If this endpoint is a Spring MVC endpoint, please use requestMatchers(MvcRequestMatcher); "
+ "otherwise, please use requestMatchers(AntPathRequestMatcher).\n\n"
+ "This is because there is more than one mappable servlet in your servlet context: %s.\n\n"
+ "For each MvcRequestMatcher, call MvcRequestMatcher#setServletPath to indicate the servlet path." ;
Map < String , Collection < String > > mappings = new LinkedHashMap < > ( ) ;
for ( ServletRegistration registration : registrations ) {
mappings . put ( registration . getClassName ( ) , registration . getMappings ( ) ) ;
}
return String . format ( template , mappings ) ;
}
/ * *
/ * *
* < p >
* < p >
* If the { @link HandlerMappingIntrospector } is available in the classpath , maps to an
* If the { @link HandlerMappingIntrospector } is available in the classpath , maps to an