I am trying to set the minimal headers to allow CORS to the same machine on different ports. I am using the latest SpringBoot and SpringSecurity as of writing theses lines. The documentation is poor and the examples are not extensive enough.
I find myself wasting too many hours on trying to figure out how to do things right, yet without success.
Bellow is my last try to configure CORS.
If any of you has any idea why ORIGIN headers are missing and how to enable them, that would be greatly appreciated.
TIA, Asaf Gery
package com.madas.restapi;
import java.util.Arrays;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.header.writers.ContentSecurityPolicyHeaderWriter;
import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authz) -> authz
.anyRequest().permitAll()
)
.headers(headers -> headers
.addHeaderWriter(new CrossOriginResourcePolicyHeaderWriter())
.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
.addHeaderWriter(new ContentSecurityPolicyHeaderWriter("object-src localhost;"))
);
return http.build();
}
}
CodePudding user response:
U have to register your cors config within the filterchain by using .cors(withDefaults())
.
For more info check out this documentation.
CodePudding user response:
As it happens most of the times, once I ask for help, I find the answer myself.
The problem with Spring Framework, is that every few versions they break their own API and invent a new way to do the same things. This practice makes Stack Overflow less useful, since it holds many historical solutions that worked for previous versions but no longer work.
So, the minimal way to enable CORS in Spring Security 5.7.3 (and probably all Spring 5.7.x versions), without any limitation on host/port, etc. (i.e. permit all), is as follows:
Configuration
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class RestConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/resource").permitAll();
return http.build();
}
}
Controller
...
@GetMapping("/resource")
@CrossOrigin(
// Access-Control-Allow-Origin
origins = { "*" },
// Alternative to origins that supports more flexible originpatterns.
// Please, see CorsConfiguration.setAllowedOriginPatterns(List)for details.
// originPatterns = { "" },
// Access-Control-Allow-Credentials
allowCredentials = "false",
// Access-Control-Allow-Headers
allowedHeaders = { "*" },
// Access-Control-Expose-Headers
exposedHeaders = { "*" },
// Access-Control-Max-Age
maxAge = 60 * 30,
// Access-Control-Allow-Methods
methods = {RequestMethod.GET}
)
public @ResponseBody ResponseEntity<CollectionModel<EntityModel<Resource>>> get() {
...
}