Skip to content

Commit 8e6bcc1

Browse files
ankurpathakjzheaux
authored andcommitted
No RequestMatcher After AnyRequest
Don't allow any type of RequestMatchers after any request by throwing IllegalStateException Fixes: gh-6359
1 parent 95e0e72 commit 8e6bcc1

File tree

2 files changed

+137
-3
lines changed

2 files changed

+137
-3
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/AbstractRequestMatcherRegistry.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
2525
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
2626
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
2727
import org.springframework.security.web.util.matcher.RequestMatcher;
28+
import org.springframework.util.Assert;
2829
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
2930

3031
import java.util.ArrayList;
@@ -39,6 +40,7 @@
3940
* @param <C> The object that is returned or Chained after creating the RequestMatcher
4041
*
4142
* @author Rob Winch
43+
* @author Ankur Pathak
4244
* @since 3.2
4345
*/
4446
public abstract class AbstractRequestMatcherRegistry<C> {
@@ -48,6 +50,8 @@ public abstract class AbstractRequestMatcherRegistry<C> {
4850

4951
private ApplicationContext context;
5052

53+
private boolean anyRequestConfigured = false;
54+
5155
protected final void setApplicationContext(ApplicationContext context) {
5256
this.context = context;
5357
}
@@ -67,7 +71,10 @@ protected final ApplicationContext getApplicationContext() {
6771
* @return the object that is chained after creating the {@link RequestMatcher}
6872
*/
6973
public C anyRequest() {
70-
return requestMatchers(ANY_REQUEST);
74+
Assert.state(!this.anyRequestConfigured, "Can't configure anyRequest after itself");
75+
C configurer = requestMatchers(ANY_REQUEST);
76+
this.anyRequestConfigured = true;
77+
return configurer;
7178
}
7279

7380
/**
@@ -97,6 +104,7 @@ public C antMatchers(HttpMethod method) {
97104
* @return the object that is chained after creating the {@link RequestMatcher}
98105
*/
99106
public C antMatchers(HttpMethod method, String... antPatterns) {
107+
Assert.state(!this.anyRequestConfigured, "Can't configure antMatchers after anyRequest");
100108
return chainRequestMatchers(RequestMatchers.antMatchers(method, antPatterns));
101109
}
102110

@@ -111,6 +119,7 @@ public C antMatchers(HttpMethod method, String... antPatterns) {
111119
* @return the object that is chained after creating the {@link RequestMatcher}
112120
*/
113121
public C antMatchers(String... antPatterns) {
122+
Assert.state(!this.anyRequestConfigured, "Can't configure antMatchers after anyRequest");
114123
return chainRequestMatchers(RequestMatchers.antMatchers(antPatterns));
115124
}
116125

@@ -160,7 +169,7 @@ public C antMatchers(String... antPatterns) {
160169
*/
161170
protected final List<MvcRequestMatcher> createMvcMatchers(HttpMethod method,
162171
String... mvcPatterns) {
163-
172+
Assert.state(!this.anyRequestConfigured, "Can't configure mvcMatchers after anyRequest");
164173
ObjectPostProcessor<Object> opp = this.context.getBean(ObjectPostProcessor.class);
165174
if (!this.context.containsBean(HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME)) {
166175
throw new NoSuchBeanDefinitionException("A Bean named " + HANDLER_MAPPING_INTROSPECTOR_BEAN_NAME +" of type " + HandlerMappingIntrospector.class.getName()
@@ -195,6 +204,7 @@ protected final List<MvcRequestMatcher> createMvcMatchers(HttpMethod method,
195204
* @return the object that is chained after creating the {@link RequestMatcher}
196205
*/
197206
public C regexMatchers(HttpMethod method, String... regexPatterns) {
207+
Assert.state(!this.anyRequestConfigured, "Can't configure regexMatchers after anyRequest");
198208
return chainRequestMatchers(RequestMatchers.regexMatchers(method, regexPatterns));
199209
}
200210

@@ -209,6 +219,7 @@ public C regexMatchers(HttpMethod method, String... regexPatterns) {
209219
* @return the object that is chained after creating the {@link RequestMatcher}
210220
*/
211221
public C regexMatchers(String... regexPatterns) {
222+
Assert.state(!this.anyRequestConfigured, "Can't configure regexMatchers after anyRequest");
212223
return chainRequestMatchers(RequestMatchers.regexMatchers(regexPatterns));
213224
}
214225

@@ -221,6 +232,7 @@ public C regexMatchers(String... regexPatterns) {
221232
* @return the object that is chained after creating the {@link RequestMatcher}
222233
*/
223234
public C requestMatchers(RequestMatcher... requestMatchers) {
235+
Assert.state(!this.anyRequestConfigured, "Can't configure requestMatchers after anyRequest");
224236
return chainRequestMatchers(Arrays.asList(requestMatchers));
225237
}
226238

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright 2002-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.security.config.annotation.web;
17+
18+
import org.junit.Test;
19+
20+
import org.springframework.beans.factory.BeanCreationException;
21+
import org.springframework.mock.web.MockServletContext;
22+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
23+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
24+
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
25+
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
26+
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
27+
28+
/**
29+
* Tests for {@link AbstractRequestMatcherRegistry}.
30+
*
31+
* @author Ankur Pathak
32+
*/
33+
public class AbstractRequestMatcherRegistryAnyMatcherTests{
34+
35+
@EnableWebSecurity
36+
static class AntMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter {
37+
protected void configure(HttpSecurity http) throws Exception {
38+
http
39+
.authorizeRequests()
40+
.anyRequest().authenticated()
41+
.antMatchers("/demo/**").permitAll();
42+
43+
}
44+
}
45+
46+
@Test(expected = BeanCreationException.class)
47+
public void antMatchersCanNotWorkAfterAnyRequest(){
48+
loadConfig(AntMatchersAfterAnyRequestConfig.class);
49+
}
50+
51+
@EnableWebSecurity
52+
static class MvcMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter {
53+
protected void configure(HttpSecurity http) throws Exception {
54+
http
55+
.authorizeRequests()
56+
.anyRequest().authenticated()
57+
.mvcMatchers("/demo/**").permitAll();
58+
59+
}
60+
}
61+
62+
@Test(expected = BeanCreationException.class)
63+
public void mvcMatchersCanNotWorkAfterAnyRequest() {
64+
loadConfig(MvcMatchersAfterAnyRequestConfig.class);
65+
}
66+
67+
@EnableWebSecurity
68+
static class RegexMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter {
69+
protected void configure(HttpSecurity http) throws Exception {
70+
http
71+
.authorizeRequests()
72+
.anyRequest().authenticated()
73+
.regexMatchers(".*").permitAll();
74+
75+
}
76+
}
77+
78+
@Test(expected = BeanCreationException.class)
79+
public void regexMatchersCanNotWorkAfterAnyRequest() {
80+
loadConfig(RegexMatchersAfterAnyRequestConfig.class);
81+
}
82+
83+
@EnableWebSecurity
84+
static class AnyRequestAfterItselfConfig extends WebSecurityConfigurerAdapter {
85+
protected void configure(HttpSecurity http) throws Exception {
86+
http
87+
.authorizeRequests()
88+
.anyRequest().authenticated()
89+
.anyRequest().permitAll();
90+
91+
}
92+
}
93+
94+
@Test(expected = BeanCreationException.class)
95+
public void anyRequestCanNotWorkAfterItself() {
96+
loadConfig(AnyRequestAfterItselfConfig.class);
97+
}
98+
99+
@EnableWebSecurity
100+
static class RequestMatchersAfterAnyRequestConfig extends WebSecurityConfigurerAdapter {
101+
protected void configure(HttpSecurity http) throws Exception {
102+
http
103+
.authorizeRequests()
104+
.anyRequest().authenticated()
105+
.requestMatchers(new AntPathRequestMatcher("/**")).permitAll();
106+
107+
}
108+
}
109+
110+
@Test(expected = BeanCreationException.class)
111+
public void requestMatchersCanNotWorkAfterAnyRequest() {
112+
loadConfig(RequestMatchersAfterAnyRequestConfig.class);
113+
}
114+
115+
private void loadConfig(Class<?>... configs) {
116+
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
117+
context.setAllowCircularReferences(false);
118+
context.register(configs);
119+
context.setServletContext(new MockServletContext());
120+
context.refresh();
121+
}
122+
}

0 commit comments

Comments
 (0)