diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java b/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java
index 35cbd8aac8..9fdcca1601 100644
--- a/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java
+++ b/config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@ import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatche
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
/**
@@ -50,12 +51,21 @@ public abstract class AbstractRequestMatcherRegistry {
private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
+ private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
+
+ private static final boolean mvcPresent;
+
private static final RequestMatcher ANY_REQUEST = AnyRequestMatcher.INSTANCE;
private ApplicationContext context;
private boolean anyRequestConfigured = false;
+ static {
+ mvcPresent = ClassUtils.isPresent(HANDLER_MAPPING_INTROSPECTOR,
+ AbstractRequestMatcherRegistry.class.getClassLoader());
+ }
+
protected final void setApplicationContext(ApplicationContext context) {
this.context = context;
}
@@ -85,7 +95,9 @@ public abstract class AbstractRequestMatcherRegistry {
* instances.
* @param method the {@link HttpMethod} to use for any {@link HttpMethod}.
* @return the object that is chained after creating the {@link RequestMatcher}
+ * @deprecated use {@link #requestMatchers(HttpMethod)} instead
*/
+ @Deprecated
public C antMatchers(HttpMethod method) {
return antMatchers(method, "/**");
}
@@ -99,7 +111,9 @@ public abstract class AbstractRequestMatcherRegistry {
* @param antPatterns the ant patterns to create. If {@code null} or empty, then
* matches on nothing.
* @return the object that is chained after creating the {@link RequestMatcher}
+ * @deprecated use {@link #requestMatchers(HttpMethod, String...)} instead
*/
+ @Deprecated
public C antMatchers(HttpMethod method, String... antPatterns) {
Assert.state(!this.anyRequestConfigured, "Can't configure antMatchers after anyRequest");
return chainRequestMatchers(RequestMatchers.antMatchers(method, antPatterns));
@@ -112,7 +126,9 @@ public abstract class AbstractRequestMatcherRegistry {
* @param antPatterns the ant patterns to create
* {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} from
* @return the object that is chained after creating the {@link RequestMatcher}
+ * @deprecated use {@link #requestMatchers(String...)} instead
*/
+ @Deprecated
public C antMatchers(String... antPatterns) {
Assert.state(!this.anyRequestConfigured, "Can't configure antMatchers after anyRequest");
return chainRequestMatchers(RequestMatchers.antMatchers(antPatterns));
@@ -132,7 +148,9 @@ public abstract class AbstractRequestMatcherRegistry {
* @param mvcPatterns the patterns to match on. The rules for matching are defined by
* Spring MVC
* @return the object that is chained after creating the {@link RequestMatcher}.
+ * @deprecated use {@link #requestMatchers(String...)} instead
*/
+ @Deprecated
public abstract C mvcMatchers(String... mvcPatterns);
/**
@@ -150,7 +168,9 @@ public abstract class AbstractRequestMatcherRegistry {
* @param mvcPatterns the patterns to match on. The rules for matching are defined by
* Spring MVC
* @return the object that is chained after creating the {@link RequestMatcher}.
+ * @deprecated use {@link #requestMatchers(HttpMethod, String...)} instead
*/
+ @Deprecated
public abstract C mvcMatchers(HttpMethod method, String... mvcPatterns);
/**
@@ -190,7 +210,10 @@ public abstract class AbstractRequestMatcherRegistry {
* @param regexPatterns the regular expressions to create
* {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} from
* @return the object that is chained after creating the {@link RequestMatcher}
+ * @deprecated use {@link #requestMatchers(RequestMatcher...)} with a
+ * {@link RegexRequestMatcher} instead
*/
+ @Deprecated
public C regexMatchers(HttpMethod method, String... regexPatterns) {
Assert.state(!this.anyRequestConfigured, "Can't configure regexMatchers after anyRequest");
return chainRequestMatchers(RequestMatchers.regexMatchers(method, regexPatterns));
@@ -203,7 +226,10 @@ public abstract class AbstractRequestMatcherRegistry {
* @param regexPatterns the regular expressions to create
* {@link org.springframework.security.web.util.matcher.RegexRequestMatcher} from
* @return the object that is chained after creating the {@link RequestMatcher}
+ * @deprecated use {@link #requestMatchers(RequestMatcher...)} with a
+ * {@link RegexRequestMatcher} instead
*/
+ @Deprecated
public C regexMatchers(String... regexPatterns) {
Assert.state(!this.anyRequestConfigured, "Can't configure regexMatchers after anyRequest");
return chainRequestMatchers(RequestMatchers.regexMatchers(regexPatterns));
@@ -250,6 +276,81 @@ public abstract class AbstractRequestMatcherRegistry {
return chainRequestMatchers(Arrays.asList(requestMatchers));
}
+ /**
+ *
+ * If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
+ * {@link MvcRequestMatcher} that also specifies a specific {@link HttpMethod} to
+ * match on. This matcher will use the same rules that Spring MVC uses for matching.
+ * For example, often times a mapping of the path "/path" will match on "/path",
+ * "/path/", "/path.html", etc. If the {@link HandlerMappingIntrospector} is not
+ * available, maps to an {@link AntPathRequestMatcher}.
+ *
+ *
+ * If a specific {@link RequestMatcher} must be specified, use
+ * {@link #requestMatchers(RequestMatcher...)} instead
+ *
+ * @param method the {@link HttpMethod} to use or {@code null} for any
+ * {@link HttpMethod}.
+ * @param patterns the patterns to match on. The rules for matching are defined by
+ * Spring MVC if {@link MvcRequestMatcher} is used
+ * @return the object that is chained after creating the {@link RequestMatcher}.
+ * @since 5.8
+ */
+ public C requestMatchers(HttpMethod method, String... patterns) {
+ List matchers = new ArrayList<>();
+ if (mvcPresent) {
+ matchers.addAll(createMvcMatchers(method, patterns));
+ }
+ else {
+ matchers.addAll(RequestMatchers.antMatchers(method, patterns));
+ }
+ return requestMatchers(matchers.toArray(new RequestMatcher[0]));
+ }
+
+ /**
+ *
+ * If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
+ * {@link MvcRequestMatcher} that does not care which {@link HttpMethod} is used. This
+ * matcher will use the same rules that Spring MVC uses for matching. For example,
+ * often times a mapping of the path "/path" will match on "/path", "/path/",
+ * "/path.html", etc. If the {@link HandlerMappingIntrospector} is not available, maps
+ * to an {@link AntPathRequestMatcher}.
+ *
+ *
+ * If a specific {@link RequestMatcher} must be specified, use
+ * {@link #requestMatchers(RequestMatcher...)} instead
+ *
+ * @param patterns the patterns to match on. The rules for matching are defined by
+ * Spring MVC if {@link MvcRequestMatcher} is used
+ * @return the object that is chained after creating the {@link RequestMatcher}.
+ * @since 5.8
+ */
+ public C requestMatchers(String... patterns) {
+ return requestMatchers(null, patterns);
+ }
+
+ /**
+ *
+ * If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
+ * {@link MvcRequestMatcher} that matches on a specific {@link HttpMethod}. This
+ * matcher will use the same rules that Spring MVC uses for matching. For example,
+ * often times a mapping of the path "/path" will match on "/path", "/path/",
+ * "/path.html", etc. If the {@link HandlerMappingIntrospector} is not available, maps
+ * to an {@link AntPathRequestMatcher}.
+ *
+ *
+ * If a specific {@link RequestMatcher} must be specified, use
+ * {@link #requestMatchers(RequestMatcher...)} instead
+ *
+ * @param method the {@link HttpMethod} to use or {@code null} for any
+ * {@link HttpMethod}.
+ * @return the object that is chained after creating the {@link RequestMatcher}.
+ * @since 5.8
+ */
+ public C requestMatchers(HttpMethod method) {
+ return requestMatchers(method, "/**");
+ }
+
/**
* Subclasses should implement this method for returning the object that is chained to
* the creation of the {@link RequestMatcher} instances.
diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
index 0781cb7837..6d626a1920 100644
--- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
+++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
@@ -28,6 +28,7 @@ import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
@@ -91,6 +92,7 @@ import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
@@ -116,7 +118,7 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
*
* @Bean
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
- * http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin();
+ * http.authorizeHttpRequests().requestMatchers("/**").hasRole("USER").and().formLogin();
* return http.build();
* }
*
@@ -140,6 +142,12 @@ import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
public final class HttpSecurity extends AbstractConfiguredSecurityBuilder
implements SecurityBuilder, HttpSecurityBuilder {
+ private static final String HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME = "mvcHandlerMappingIntrospector";
+
+ private static final String HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector";
+
+ private static final boolean mvcPresent;
+
private final RequestMatcherConfigurer requestMatcherConfigurer;
private List filters = new ArrayList<>();
@@ -150,6 +158,10 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder
* @return the {@link RequestMatcherConfigurer} for further customizations
+ * @deprecated use {@link #securityMatchers()} instead
*/
+ @Deprecated
public RequestMatcherConfigurer requestMatchers() {
return this.requestMatcherConfigurer;
}
@@ -3325,7 +3339,9 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder requestMatcherCustomizer) {
requestMatcherCustomizer.customize(this.requestMatcherConfigurer);
return HttpSecurity.this;
@@ -3345,15 +3361,318 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder
+ * Invoking {@link #securityMatchers()} will not override previous invocations of
+ * {@link #securityMatchers()}}, {@link #securityMatchers(Customizer)}
+ * {@link #securityMatcher(String)} and {@link #securityMatcher(RequestMatcher)}
+ *
+ *
+ *
Example Configurations
+ *
+ * The following configuration enables the {@link HttpSecurity} for URLs that begin
+ * with "/api/" or "/oauth/".
+ *
+ *
+ * @return the {@link RequestMatcherConfigurer} for further customizations
+ */
+ public RequestMatcherConfigurer securityMatchers() {
+ return this.requestMatcherConfigurer;
+ }
+
+ /**
+ * Allows specifying which {@link HttpServletRequest} instances this
+ * {@link HttpSecurity} will be invoked on. This method allows for easily invoking the
+ * {@link HttpSecurity} for multiple different {@link RequestMatcher} instances. If
+ * only a single {@link RequestMatcher} is necessary consider using
+ * {@link #securityMatcher(String)}, or {@link #securityMatcher(RequestMatcher)}.
+ *
+ *
+ * Invoking {@link #securityMatchers(Customizer)} will not override previous
+ * invocations of {@link #securityMatchers()}}, {@link #securityMatchers(Customizer)}
+ * {@link #securityMatcher(String)} and {@link #securityMatcher(RequestMatcher)}
+ *
+ *
+ *
Example Configurations
+ *
+ * The following configuration enables the {@link HttpSecurity} for URLs that begin
+ * with "/api/" or "/oauth/".
+ *
+ *
+ * @param requestMatcherCustomizer the {@link Customizer} to provide more options for
+ * the {@link RequestMatcherConfigurer}
+ * @return the {@link HttpSecurity} for further customizations
+ */
+ public HttpSecurity securityMatchers(Customizer requestMatcherCustomizer) {
+ requestMatcherCustomizer.customize(this.requestMatcherConfigurer);
+ return HttpSecurity.this;
+ }
+
+ /**
+ * Allows configuring the {@link HttpSecurity} to only be invoked when matching the
+ * provided {@link RequestMatcher}. If more advanced configuration is necessary,
+ * consider using {@link #securityMatchers(Customizer)} ()}.
+ *
+ *
+ * @param requestMatcher the {@link RequestMatcher} to use (i.e. new
+ * AntPathRequestMatcher("/admin/**","GET") )
+ * @return the {@link HttpSecurity} for further customizations
+ * @see #securityMatcher(String)
+ */
+ public HttpSecurity securityMatcher(RequestMatcher requestMatcher) {
+ this.requestMatcher = requestMatcher;
+ return this;
+ }
+
+ /**
+ * Allows configuring the {@link HttpSecurity} to only be invoked when matching the
+ * provided pattern. This method creates a {@link MvcRequestMatcher} if Spring MVC is
+ * in the classpath or creates an {@link AntPathRequestMatcher} if not. If more
+ * advanced configuration is necessary, consider using
+ * {@link #securityMatchers(Customizer)} or {@link #securityMatcher(RequestMatcher)}.
+ *
+ *
+ * Invoking {@link #securityMatcher(String)} will override previous invocations of
+ * {@link #mvcMatcher(String)}}, {@link #requestMatchers()},
+ * {@link #antMatcher(String)}, {@link #regexMatcher(String)}, and
+ * {@link #requestMatcher(RequestMatcher)}.
+ *
+ * @param pattern the pattern to match on (i.e. "/admin/**")
+ * @return the {@link HttpSecurity} for further customizations
+ * @see AntPathRequestMatcher
+ * @see MvcRequestMatcher
+ */
+ public HttpSecurity securityMatcher(String pattern) {
+ if (!mvcPresent) {
+ this.requestMatcher = new AntPathRequestMatcher(pattern);
+ return this;
+ }
+ if (!getContext().containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
+ throw new NoSuchBeanDefinitionException("A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME
+ + " of type " + HandlerMappingIntrospector.class.getName()
+ + " is required to use MvcRequestMatcher. Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext.");
+ }
+ HandlerMappingIntrospector introspector = getContext().getBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME,
+ HandlerMappingIntrospector.class);
+ this.requestMatcher = new MvcRequestMatcher(introspector, pattern);
+ return this;
+ }
+
/**
* Allows configuring the {@link HttpSecurity} to only be invoked when matching the
* provided ant pattern. If more advanced configuration is necessary, consider using
@@ -3367,8 +3686,10 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder
* @param antPattern the Ant Pattern to match on (i.e. "/admin/**")
* @return the {@link HttpSecurity} for further customizations
+ * @deprecated use {@link #securityMatcher(String)} instead
* @see AntPathRequestMatcher
*/
+ @Deprecated
public HttpSecurity antMatcher(String antPattern) {
return requestMatcher(new AntPathRequestMatcher(antPattern));
}
@@ -3386,8 +3707,10 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder
* @param mvcPattern the Spring MVC Pattern to match on (i.e. "/admin/**")
* @return the {@link HttpSecurity} for further customizations
+ * @deprecated use {@link #securityMatcher(String)} instead
* @see MvcRequestMatcher
*/
+ @Deprecated
public HttpSecurity mvcMatcher(String mvcPattern) {
HandlerMappingIntrospector introspector = new HandlerMappingIntrospector();
introspector.setApplicationContext(getContext());
@@ -3408,8 +3731,10 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder
* @param pattern the Regular Expression to match on (i.e. "/admin/.+")
* @return the {@link HttpSecurity} for further customizations
- * @see RegexRequestMatcher
+ * @deprecated use {@link #securityMatcher(RequestMatcher)} with a
+ * {@link RegexRequestMatcher} instead
*/
+ @Deprecated
public HttpSecurity regexMatcher(String pattern) {
return requestMatcher(new RegexRequestMatcher(pattern, null));
}
@@ -3480,14 +3805,22 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder mvcMatchers = createMvcMatchers(method, mvcPatterns);
setMatchers(mvcMatchers);
return new MvcMatchersRequestMatcherConfigurer(getContext(), mvcMatchers, this.matchers);
}
+ /**
+ * @deprecated use {@link #requestMatchers(String...)} instead
+ */
@Override
+ @Deprecated
public MvcMatchersRequestMatcherConfigurer mvcMatchers(String... patterns) {
return mvcMatchers(null, patterns);
}
@@ -3500,7 +3833,7 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder requestMatchers) {
this.matchers.addAll(requestMatchers);
- requestMatcher(new OrRequestMatcher(this.matchers));
+ securityMatcher(new OrRequestMatcher(this.matchers));
}
/**
diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java
index 299b92fcf3..7f0fabc705 100644
--- a/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java
+++ b/config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java
@@ -135,7 +135,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder
* webSecurityBuilder.ignoring()
* // ignore all URLs that start with /resources/ or /static/
- * .antMatchers("/resources/**", "/static/**");
+ * .requestMatchers("/resources/**", "/static/**");
*
*
* Alternatively this will accomplish the same result:
@@ -143,7 +143,7 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder
* webSecurityBuilder.ignoring()
* // ignore all URLs that start with /resources/ or /static/
- * .antMatchers("/resources/**").antMatchers("/static/**");
+ * .requestMatchers("/resources/**").requestMatchers("/static/**");
*
*
* Multiple invocations of ignoring() are also additive, so the following is also
@@ -152,10 +152,10 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder
* webSecurityBuilder.ignoring()
* // ignore all URLs that start with /resources/
- * .antMatchers("/resources/**");
+ * .requestMatchers("/resources/**");
* webSecurityBuilder.ignoring()
* // ignore all URLs that start with /static/
- * .antMatchers("/static/**");
+ * .requestMatchers("/static/**");
* // now both URLs that start with /resources/ and /static/ will be ignored
*
* @return the {@link IgnoredRequestConfigurer} to use for registering request that
@@ -380,7 +380,9 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder mvcMatchers;
@@ -412,14 +414,22 @@ public final class WebSecurity extends AbstractConfiguredSecurityBuilder mvcMatchers = createMvcMatchers(method, mvcPatterns);
WebSecurity.this.ignoredRequests.addAll(mvcMatchers);
return new MvcMatchersIgnoredRequestConfigurer(getApplicationContext(), mvcMatchers);
}
+ /**
+ * @deprecated use {@link #requestMatchers(String...)} instead
+ */
@Override
+ @Deprecated
public MvcMatchersIgnoredRequestConfigurer mvcMatchers(String... mvcPatterns) {
return mvcMatchers(null, mvcPatterns);
}
diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurity.java
index 1ea088541a..7230d65957 100644
--- a/config/src/main/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurity.java
+++ b/config/src/main/java/org/springframework/security/config/annotation/web/configuration/EnableWebSecurity.java
@@ -41,12 +41,12 @@ import org.springframework.security.web.SecurityFilterChain;
* public WebSecurityCustomizer webSecurityCustomizer() {
* return (web) -> web.ignoring()
* // Spring Security should completely ignore URLs starting with /resources/
- * .antMatchers("/resources/**");
+ * .requestMatchers("/resources/**");
* }
*
* @Bean
* public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
- * http.authorizeRequests().antMatchers("/public/**").permitAll().anyRequest()
+ * http.authorizeRequests().requestMatchers("/public/**").permitAll().anyRequest()
* .hasRole("USER").and()
* // Possibly more configuration ...
* .formLogin() // enable form based log in
diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurer.java
index 820aa324be..9f6395f8ae 100644
--- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurer.java
+++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurer.java
@@ -146,12 +146,20 @@ public final class AuthorizeHttpRequestsConfigurer matchers) {
diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java
index eaa466f4a8..c46fab8e76 100644
--- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java
+++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/CsrfConfigurer.java
@@ -163,7 +163,10 @@ public final class CsrfConfigurer>
*
*
* @since 4.0
+ * @deprecated use {@link #ignoringRequestMatchers(RequestMatcher...)} with an
+ * {@link org.springframework.security.web.util.matcher.AntPathRequestMatcher} instead
*/
+ @Deprecated
public CsrfConfigurer ignoringAntMatchers(String... antPatterns) {
return new IgnoreCsrfProtectionRegistry(this.context).antMatchers(antPatterns).and();
}
@@ -197,6 +200,35 @@ public final class CsrfConfigurer>
return new IgnoreCsrfProtectionRegistry(this.context).requestMatchers(requestMatchers).and();
}
+ /**
+ *
+ * Allows specifying {@link HttpServletRequest} that should not use CSRF Protection
+ * even if they match the {@link #requireCsrfProtectionMatcher(RequestMatcher)}.
+ *
+ *
+ *
+ * For example, the following configuration will ensure CSRF protection ignores:
+ *
+ *
+ *
Any GET, HEAD, TRACE, OPTIONS (this is the default)
+ *
We also explicitly state to ignore any request that starts with "/sockjs/"
* Specify the {@link SessionAuthenticationStrategy} to use. The default is a
@@ -350,14 +382,22 @@ public final class CsrfConfigurer>
setApplicationContext(context);
}
+ /**
+ * @deprecated use {@link #requestMatchers(HttpMethod, String...)} instead
+ */
@Override
+ @Deprecated
public MvcMatchersIgnoreCsrfProtectionRegistry mvcMatchers(HttpMethod method, String... mvcPatterns) {
List mvcMatchers = createMvcMatchers(method, mvcPatterns);
CsrfConfigurer.this.ignoredCsrfProtectionMatchers.addAll(mvcMatchers);
return new MvcMatchersIgnoreCsrfProtectionRegistry(getApplicationContext(), mvcMatchers);
}
+ /**
+ * @deprecated use {@link #requestMatchers(String...)} instead
+ */
@Override
+ @Deprecated
public MvcMatchersIgnoreCsrfProtectionRegistry mvcMatchers(String... mvcPatterns) {
return mvcMatchers(null, mvcPatterns);
}
diff --git a/config/src/main/kotlin/org/springframework/security/config/annotation/web/CsrfDsl.kt b/config/src/main/kotlin/org/springframework/security/config/annotation/web/CsrfDsl.kt
index 0ed411416c..26986e9e13 100644
--- a/config/src/main/kotlin/org/springframework/security/config/annotation/web/CsrfDsl.kt
+++ b/config/src/main/kotlin/org/springframework/security/config/annotation/web/CsrfDsl.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2020 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@ class CsrfDsl {
private var ignoringAntMatchers: Array? = null
private var ignoringRequestMatchers: Array? = null
+ private var ignoringRequestMatchersPatterns: Array? = null
private var disabled = false
/**
@@ -66,6 +67,16 @@ class CsrfDsl {
ignoringRequestMatchers = requestMatchers
}
+ /**
+ * Allows specifying [HttpServletRequest]s that should not use CSRF Protection
+ * even if they match the [requireCsrfProtectionMatcher].
+ *
+ * @param patterns the patterns that should not use CSRF protection
+ */
+ fun ignoringRequestMatchers(vararg patterns: String) {
+ ignoringRequestMatchersPatterns = patterns
+ }
+
/**
* Disable CSRF protection
*/
@@ -80,6 +91,7 @@ class CsrfDsl {
sessionAuthenticationStrategy?.also { csrf.sessionAuthenticationStrategy(sessionAuthenticationStrategy) }
ignoringAntMatchers?.also { csrf.ignoringAntMatchers(*ignoringAntMatchers!!) }
ignoringRequestMatchers?.also { csrf.ignoringRequestMatchers(*ignoringRequestMatchers!!) }
+ ignoringRequestMatchersPatterns?.also { csrf.ignoringRequestMatchers(*ignoringRequestMatchersPatterns!!) }
if (disabled) {
csrf.disable()
}
diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java
index 46b7af5284..d5ebd3106a 100644
--- a/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java
+++ b/config/src/test/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistryTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,19 +16,28 @@
package org.springframework.security.config.annotation.web;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
import java.util.List;
import jakarta.servlet.DispatcherType;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpMethod;
+import org.springframework.security.config.annotation.ObjectPostProcessor;
+import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher;
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.mock;
/**
* Tests for {@link AbstractRequestMatcherRegistry}.
@@ -37,11 +46,21 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class AbstractRequestMatcherRegistryTests {
+ private static final ObjectPostProcessor