Skip to content

Commit d2d9da0

Browse files
committed
Favor PathPatternRequestMatcher
Issue gh-16828
1 parent e65e32b commit d2d9da0

File tree

1 file changed

+59
-28
lines changed

1 file changed

+59
-28
lines changed

config/src/main/java/org/springframework/security/config/http/OAuth2LoginBeanDefinitionParser.java

Lines changed: 59 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,20 @@
1919
import java.util.Arrays;
2020
import java.util.Collections;
2121
import java.util.HashMap;
22-
import java.util.LinkedHashMap;
2322
import java.util.List;
2423
import java.util.Map;
2524

2625
import org.w3c.dom.Element;
2726

2827
import org.springframework.beans.BeanMetadataElement;
2928
import org.springframework.beans.BeansException;
29+
import org.springframework.beans.factory.FactoryBean;
3030
import org.springframework.beans.factory.config.BeanDefinition;
3131
import org.springframework.beans.factory.config.BeanReference;
3232
import org.springframework.beans.factory.config.RuntimeBeanReference;
3333
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
3434
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
35+
import org.springframework.beans.factory.support.ManagedMap;
3536
import org.springframework.beans.factory.xml.BeanDefinitionParser;
3637
import org.springframework.beans.factory.xml.ParserContext;
3738
import org.springframework.context.ApplicationContext;
@@ -57,7 +58,6 @@
5758
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
5859
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
5960
import org.springframework.security.web.util.matcher.AndRequestMatcher;
60-
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
6161
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
6262
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
6363
import org.springframework.security.web.util.matcher.OrRequestMatcher;
@@ -235,7 +235,7 @@ public BeanDefinition parse(Element element, ParserContext parserContext) {
235235
.getBeanDefinition();
236236
}
237237
else {
238-
Map<RequestMatcher, AuthenticationEntryPoint> entryPoint = getLoginEntryPoint(element);
238+
Map<BeanDefinition, AuthenticationEntryPoint> entryPoint = getLoginEntryPoint(element);
239239
if (entryPoint != null) {
240240
this.oauth2LoginAuthenticationEntryPoint = BeanDefinitionBuilder
241241
.rootBeanDefinition(DelegatingAuthenticationEntryPoint.class)
@@ -364,42 +364,35 @@ BeanDefinition getOAuth2LoginLinks() {
364364
return this.oauth2LoginLinks;
365365
}
366366

367-
private Map<RequestMatcher, AuthenticationEntryPoint> getLoginEntryPoint(Element element) {
368-
Map<RequestMatcher, AuthenticationEntryPoint> entryPoints = null;
367+
private Map<BeanDefinition, AuthenticationEntryPoint> getLoginEntryPoint(Element element) {
368+
Map<BeanDefinition, AuthenticationEntryPoint> entryPoints = null;
369369
Element clientRegsElt = DomUtils.getChildElementByTagName(element.getOwnerDocument().getDocumentElement(),
370370
Elements.CLIENT_REGISTRATIONS);
371371
if (clientRegsElt != null) {
372372
List<Element> clientRegList = DomUtils.getChildElementsByTagName(clientRegsElt, ELT_CLIENT_REGISTRATION);
373373
if (clientRegList.size() == 1) {
374-
RequestMatcher loginPageMatcher = new AntPathRequestMatcher(DEFAULT_LOGIN_URI);
375-
RequestMatcher faviconMatcher = new AntPathRequestMatcher("/favicon.ico");
376-
RequestMatcher defaultEntryPointMatcher = this.getAuthenticationEntryPointMatcher();
377-
RequestMatcher defaultLoginPageMatcher = new AndRequestMatcher(
378-
new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher);
379-
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
380-
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
374+
BeanDefinition loginPageMatcher = BeanDefinitionBuilder
375+
.rootBeanDefinition(RequestMatcherFactoryBean.class)
376+
.addConstructorArgValue(DEFAULT_LOGIN_URI)
377+
.getBeanDefinition();
378+
BeanDefinition faviconMatcher = BeanDefinitionBuilder
379+
.rootBeanDefinition(RequestMatcherFactoryBean.class)
380+
.addConstructorArgValue("/favicon.ico")
381+
.getBeanDefinition();
382+
BeanDefinition entryPointMatcher = BeanDefinitionBuilder
383+
.rootBeanDefinition(EntryPointMatcherFactoryBean.class)
384+
.addConstructorArgValue(loginPageMatcher)
385+
.addConstructorArgValue(faviconMatcher)
386+
.getBeanDefinition();
381387
Element clientRegElt = clientRegList.get(0);
382-
entryPoints = new LinkedHashMap<>();
383-
entryPoints.put(
384-
new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher)),
385-
new LoginUrlAuthenticationEntryPoint(DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/"
386-
+ clientRegElt.getAttribute(ATT_REGISTRATION_ID)));
388+
entryPoints = new ManagedMap<>();
389+
entryPoints.put(entryPointMatcher, new LoginUrlAuthenticationEntryPoint(
390+
DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + clientRegElt.getAttribute(ATT_REGISTRATION_ID)));
387391
}
388392
}
389393
return entryPoints;
390394
}
391395

392-
private RequestMatcher getAuthenticationEntryPointMatcher() {
393-
ContentNegotiationStrategy contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
394-
MediaTypeRequestMatcher mediaMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy,
395-
MediaType.APPLICATION_XHTML_XML, new MediaType("image", "*"), MediaType.TEXT_HTML,
396-
MediaType.TEXT_PLAIN);
397-
mediaMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
398-
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
399-
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
400-
return new AndRequestMatcher(Arrays.asList(notXRequestedWith, mediaMatcher));
401-
}
402-
403396
private static class OidcAuthenticationRequestChecker implements AuthenticationProvider {
404397

405398
@Override
@@ -463,4 +456,42 @@ Map<String, String> getLoginLinks() {
463456

464457
}
465458

459+
@Deprecated
460+
static class EntryPointMatcherFactoryBean implements FactoryBean<RequestMatcher> {
461+
462+
private final RequestMatcher entryPointMatcher;
463+
464+
EntryPointMatcherFactoryBean(RequestMatcher loginPageMatcher, RequestMatcher faviconMatcher) {
465+
RequestMatcher defaultEntryPointMatcher = getAuthenticationEntryPointMatcher();
466+
RequestMatcher defaultLoginPageMatcher = new AndRequestMatcher(
467+
new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher);
468+
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
469+
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
470+
this.entryPointMatcher = new AndRequestMatcher(notXRequestedWith,
471+
new NegatedRequestMatcher(defaultLoginPageMatcher));
472+
}
473+
474+
private RequestMatcher getAuthenticationEntryPointMatcher() {
475+
ContentNegotiationStrategy contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
476+
MediaTypeRequestMatcher mediaMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy,
477+
MediaType.APPLICATION_XHTML_XML, new MediaType("image", "*"), MediaType.TEXT_HTML,
478+
MediaType.TEXT_PLAIN);
479+
mediaMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
480+
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
481+
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
482+
return new AndRequestMatcher(Arrays.asList(notXRequestedWith, mediaMatcher));
483+
}
484+
485+
@Override
486+
public RequestMatcher getObject() {
487+
return this.entryPointMatcher;
488+
}
489+
490+
@Override
491+
public Class<?> getObjectType() {
492+
return RequestMatcher.class;
493+
}
494+
495+
}
496+
466497
}

0 commit comments

Comments
 (0)