Skip to content

Commit cdda121

Browse files
committed
fix: Restrict automatic CORS configuration to UrlBasedCorsConfigurationSource
- Update CORS configuration logic to automatically enable .cors() only if a UrlBasedCorsConfigurationSource bean is present. - Modify applyCorsIfAvailable method to check for UrlBasedCorsConfigurationSource instances.
1 parent 5089b88 commit cdda121

File tree

3 files changed

+48
-5
lines changed

3 files changed

+48
-5
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 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.
@@ -48,13 +48,15 @@
4848
import org.springframework.web.accept.ContentNegotiationStrategy;
4949
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
5050
import org.springframework.web.cors.CorsConfigurationSource;
51+
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
5152

5253
import static org.springframework.security.config.Customizer.withDefaults;
5354

5455
/**
5556
* {@link Configuration} that exposes the {@link HttpSecurity} bean.
5657
*
5758
* @author Eleftheria Stein
59+
* @author Jinwoo Bae
5860
* @since 5.4
5961
*/
6062
@Configuration(proxyBeanMethods = false)
@@ -131,8 +133,13 @@ HttpSecurity httpSecurity() throws Exception {
131133
}
132134

133135
private void applyCorsIfAvailable(HttpSecurity http) throws Exception {
134-
String[] beanNames = this.context.getBeanNamesForType(CorsConfigurationSource.class);
135-
if (beanNames.length == 1) {
136+
Map<String, CorsConfigurationSource> corsConfigurationSources = this.context
137+
.getBeansOfType(CorsConfigurationSource.class);
138+
139+
boolean hasUrlBasedCorsConfigurationSource = corsConfigurationSources.values()
140+
.stream()
141+
.anyMatch(UrlBasedCorsConfigurationSource.class::isInstance);
142+
if (hasUrlBasedCorsConfigurationSource) {
136143
http.cors(withDefaults());
137144
}
138145
}

config/src/test/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfigurationTests.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 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.
@@ -374,6 +374,15 @@ public void configureWhenCorsConfigurationSourceThenApplyCors() {
374374
assertThat(configSource).isInstanceOf(UrlBasedCorsConfigurationSource.class);
375375
}
376376

377+
@Test
378+
public void configureWhenNoCorsConfigurationSourceThenNoCorsApplied() throws Exception {
379+
this.spring.register(NonUrlBasedCorsConfig.class, DefaultWithFilterChainConfig.class).autowire();
380+
SecurityFilterChain filterChain = this.spring.getContext().getBean(SecurityFilterChain.class);
381+
assertThat(filterChain.getFilters()).noneMatch((filter) -> filter instanceof CorsFilter);
382+
383+
this.mockMvc.perform(formLogin()).andExpect(header().doesNotExist("Access-Control-Allow-Origin"));
384+
}
385+
377386
@Test
378387
public void configureWhenAddingCustomDslUsingWithThenApplied() throws Exception {
379388
this.spring.register(WithCustomDslConfig.class, UserDetailsConfig.class).autowire();
@@ -673,6 +682,33 @@ CorsConfigurationSource corsConfigurationSource() {
673682

674683
}
675684

685+
@Configuration
686+
@EnableWebSecurity
687+
static class NonUrlBasedCorsConfig {
688+
689+
@Bean
690+
CorsConfigurationSource corsConfigurationSource() {
691+
return new CustomCorsConfigurationSource();
692+
}
693+
694+
@Bean
695+
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
696+
return http.build();
697+
}
698+
699+
}
700+
701+
static class CustomCorsConfigurationSource implements CorsConfigurationSource {
702+
703+
@Override
704+
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
705+
CorsConfiguration configuration = new CorsConfiguration();
706+
configuration.setAllowedOrigins(List.of("http://localhost:8080"));
707+
return configuration;
708+
}
709+
710+
}
711+
676712
static class DefaultConfigurer extends AbstractHttpConfigurer<DefaultConfigurer, HttpSecurity> {
677713

678714
boolean init;

docs/modules/ROOT/pages/servlet/integrations/cors.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ CORS must be processed before Spring Security, because the pre-flight request do
66
If the request does not contain any cookies and Spring Security is first, the request determines that the user is not authenticated (since there are no cookies in the request) and rejects it.
77

88
The easiest way to ensure that CORS is handled first is to use the `CorsFilter`.
9-
Users can integrate the `CorsFilter` with Spring Security by providing a `CorsConfigurationSource`.
9+
Users can integrate the `CorsFilter` with Spring Security by providing a `CorsConfigurationSource`. Note that Spring Security will automatically configure CORS only if a `UrlBasedCorsConfigurationSource` instance is present.
1010
For example, the following will integrate CORS support within Spring Security:
1111

1212
[tabs]

0 commit comments

Comments
 (0)