It could be useful to add with a less of code the expected CORS headers in your Spring boot configuration. Let's do this!
CORS (Cross-Origin Resource Sharing) is a mechanism that allows "to protect" your resources APIs from undesirated calls. By saying protect I mean restrict the resources to be requested by any domain outside the origin domain where the resources was served.
Flag all resources with @CrossOrigin
This is the only step required by the configurer to claim the cross origin resource sharing. For example :
@CrossOrigin
@RestController
@RequestMapping(value = "/api/user")
public interface UserController { ...
Declare the CORS Spring configurer
This Spring bean is responsible of several things 🔎 The first one action is to scan your resources looking for the paths will should be protected. In this example we use the autowired bean ApplicationContext
as entry point in the Spring application context :
@Autowired
public CorsConfig(ApplicationContext applicationContext) {
corsControllers = Stream.of(applicationContext.getBeanNamesForAnnotation(CrossOrigin.class))
.filter(Objects::nonNull)
.map(bean -> applicationContext.findAnnotationOnBean(bean, RequestMapping.class))
.filter(mapping -> Objects.nonNull(mapping) && mapping.path().length > 0)
.map(mapping -> mapping.path()[0])
.peek(path -> log.info("Register CORS configuration for \"{}\".", path))
.collect(toSet());
}
Please keep this code safe !
The second one action is to declare WebMvcConfigurer
bean will add the protected path in the CORS Registry.
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
for (String corsController : corsControllers) {
registry.addMapping(corsController)
.allowedOriginPatterns(allowedCorsOrigin)
.allowedHeaders("Authorization", ...)
.allowedMethods("OPTIONS", "PUT", "POST", ...);
}
}
};
}
Something interresting to note there is that we can externalize the declaration of allowed domains by Ant patterns in an array of String. The property allowedCorsOrigin is a variable annoted by @Value (see the sample code).
Test the Spring configuration with CURL
Now we are able to test the configuration in a real Spring app.
🟢Here we use a valid domain for test :
❯ curl -H "Origin: https://fr.reservoircode.net" --verbose http://localhost:9999/api/user
* Trying 127.0.0.1:9999...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 9999 (#0)
> GET /api/user HTTP/1.1
> Host: localhost:9999
> User-Agent: curl/7.68.0
> Accept: */*
> Origin: https://fr.reservoircode.net
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Access-Control-Allow-Origin: https://fr.reservoircode.net
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Fri, 20 May 2022 16:20:17 GMT
<
* Connection #0 to host localhost left intact
{"id":"1","name":"Ulrich"}
🔴Here we use a invalid domain for test :
❯ curl -H "Origin: https://foo.com" --verbose http://localhost:9999/api/user
* Trying 127.0.0.1:9999...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 9999 (#0)
> GET /api/user HTTP/1.1
> Host: localhost:9999
> User-Agent: curl/7.68.0
> Accept: */*
> Origin: https://foo.com
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 403
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Transfer-Encoding: chunked
< Date: Fri, 20 May 2022 16:23:02 GMT
<
* Connection #0 to host localhost left intact
Invalid CORS request
Let me try it
If you want a Spring boot example you can clone the repository https://github.com/ulrich/spring-cors-autoconfig
Crédit photo : https://pixabay.com/fr/users/jackmac34-483877/
Top comments (0)