No RequestMatcher After AnyRequest

Don't allow any type of RequestMatchers
after any request by throwing IllegalStateException

Fixes: gh-6359
This commit is contained in:
Ankur Pathak 2019-01-20 04:15:43 +05:30 committed by Josh Cummings
parent 95e0e7243d
commit 8e6bcc1c35
2 changed files with 137 additions and 3 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -25,6 +25,7 @@ import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
import java.util.ArrayList;
@ -39,6 +40,7 @@ import java.util.List;
* @param <C> The object that is returned or Chained after creating the RequestMatcher
*
* @author Rob Winch
* @author Ankur Pathak
* @since 3.2
*/
public abstract class AbstractRequestMatcherRegistry<C> {
@ -48,6 +50,8 @@ public abstract class AbstractRequestMatcherRegistry<C> {
private ApplicationContext context;
private boolean anyRequestConfigured = false;
protected final void setApplicationContext(ApplicationContext context) {
this.context = context;
}
@ -67,7 +71,10 @@ public abstract class AbstractRequestMatcherRegistry<C> {
* @return the object that is chained after creating the {@link RequestMatcher}
*/
public C anyRequest() {
return requestMatchers(ANY_REQUEST);
Assert.state(!this.anyRequestConfigured, "Can't configure anyRequest after itself");
C configurer = requestMatchers(ANY_REQUEST);
this.anyRequestConfigured = true;
return configurer;
}
/**
@ -97,6 +104,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
* @return the object that is chained after creating the {@link RequestMatcher}
*/
public C antMatchers(HttpMethod method, String... antPatterns) {
Assert.state(!this.anyRequestConfigured, "Can't configure antMatchers after anyRequest");
return chainRequestMatchers(RequestMatchers.antMatchers(method, antPatterns));
}
@ -111,6 +119,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
* @return the object that is chained after creating the {@link RequestMatcher}
*/
public C antMatchers(String... antPatterns) {
Assert.state(!this.anyRequestConfigured, "Can't configure antMatchers after anyRequest");
return chainRequestMatchers(RequestMatchers.antMatchers(antPatterns));
}
@ -160,7 +169,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
*/
protected final List<MvcRequestMatcher> createMvcMatchers(HttpMethod method,
String... mvcPatterns) {
Assert.state(!this.anyRequestConfigured, "Can't configure mvcMatchers after anyRequest");
ObjectPostProcessor<Object> opp = this.context.getBean(ObjectPostProcessor.class);
if (!this.context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
throw new NoSuchBeanDefinitionException("A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME +" of type " + HandlerMappingIntrospector.class.getName()
@ -195,6 +204,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
* @return the object that is chained after creating the {@link RequestMatcher}
*/
public C regexMatchers(HttpMethod method, String... regexPatterns) {
Assert.state(!this.anyRequestConfigured, "Can't configure regexMatchers after anyRequest");
return chainRequestMatchers(RequestMatchers.regexMatchers(method, regexPatterns));
}
@ -209,6 +219,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
* @return the object that is chained after creating the {@link RequestMatcher}
*/
public C regexMatchers(String... regexPatterns) {
Assert.state(!this.anyRequestConfigured, "Can't configure regexMatchers after anyRequest");
return chainRequestMatchers(RequestMatchers.regexMatchers(regexPatterns));
}
@ -221,6 +232,7 @@ public abstract class AbstractRequestMatcherRegistry<C> {
* @return the object that is chained after creating the {@link RequestMatcher}
*/
public C requestMatchers(RequestMatcher... requestMatchers) {
Assert.state(!this.anyRequestConfigured, "Can't configure requestMatchers after anyRequest");
return chainRequestMatchers(Arrays.asList(requestMatchers));
}

View File

@ -0,0 +1,122 @@
/*
* Copyright 2002-2019 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.config.annotation.web;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.mock.web.MockServletContext;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
/**
* Tests for {@link AbstractRequestMatcherRegistry}.
*
* @author Ankur Pathak
*/
public class AbstractRequestMatcherRegistryAnyMatcherTests{
@EnableWebSecurity
static class AntMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.antMatchers("/demo/**").permitAll();
}
}
@Test(expected = BeanCreationException.class)
public void antMatchersCanNotWorkAfterAnyRequest(){
loadConfig(AntMatchersAfterAnyRequestConfig.class);
}
@EnableWebSecurity
static class MvcMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.mvcMatchers("/demo/**").permitAll();
}
}
@Test(expected = BeanCreationException.class)
public void mvcMatchersCanNotWorkAfterAnyRequest() {
loadConfig(MvcMatchersAfterAnyRequestConfig.class);
}
@EnableWebSecurity
static class RegexMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.regexMatchers(".*").permitAll();
}
}
@Test(expected = BeanCreationException.class)
public void regexMatchersCanNotWorkAfterAnyRequest() {
loadConfig(RegexMatchersAfterAnyRequestConfig.class);
}
@EnableWebSecurity
static class AnyRequestAfterItselfConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.anyRequest().permitAll();
}
}
@Test(expected = BeanCreationException.class)
public void anyRequestCanNotWorkAfterItself() {
loadConfig(AnyRequestAfterItselfConfig.class);
}
@EnableWebSecurity
static class RequestMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.requestMatchers(new AntPathRequestMatcher("/**")).permitAll();
}
}
@Test(expected = BeanCreationException.class)
public void requestMatchersCanNotWorkAfterAnyRequest() {
loadConfig(RequestMatchersAfterAnyRequestConfig.class);
}
private void loadConfig(Class<?>... configs) {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setAllowCircularReferences(false);
context.register(configs);
context.setServletContext(new MockServletContext());
context.refresh();
}
}