How does Spring Boot handle cross-origin requests (CORS)?
Cross-Origin Resource Sharing (CORS) is a security mechanism enforced by web browsers to restrict web pages from making requests to a different domain than the one that served the web page. Spring Boot provides flexible and robust ways to configure CORS, allowing developers to control which origins can access resources served by their applications.
Understanding CORS
CORS is a browser security feature that prevents a web page from making requests to a different domain, protocol, or port than the one that served the initial page. This "same-origin policy" protects users from malicious scripts. When a web application needs to access resources from a different origin, the server hosting the resources must explicitly grant permission using CORS headers.
Spring Boot's Approach to CORS
Spring Boot, built on Spring Framework, offers several convenient ways to manage CORS settings, ranging from fine-grained control at the method level to global configurations across the entire application.
1. Global CORS Configuration
For consistent CORS policies across multiple controllers or the entire application, Spring Boot allows you to define a global CORS configuration. This is typically done by implementing the WebMvcConfigurer interface and overriding the addCorsMappings method.
package com.example.demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // Apply to all endpoints
.allowedOrigins("http://localhost:4200", "http://another-domain.com") // Specific origins
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // Allowed HTTP methods
.allowedHeaders("*") // Allow all headers
.allowCredentials(true); // Allow sending of cookies, auth headers
// .maxAge(3600); // Optional: Max age for preflight caching (seconds)
}
}
2. Controller-level CORS Configuration (`@CrossOrigin`)
For more specific control, the @CrossOrigin annotation can be applied at the controller class level or individual method level. This provides fine-tuned CORS policies for particular endpoints, overriding any global configurations if specified.
package com.example.demo.controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://localhost:4200", methods = { "GET", "POST" }) // Class-level
public class MyController {
@GetMapping("/public-data")
public String getPublicData() {
return "This is public data.";
}
@CrossOrigin(origins = "http://another-domain.com") // Method-level override/addition
@GetMapping("/private-data")
public String getPrivateData() {
return "This is private data for another domain.";
}
}
3. Filter-based CORS Configuration
For highly customized or programmatic CORS handling, especially in non-web MVC applications or when integrating with other filters, Spring provides the CorsFilter. This filter uses a CorsConfigurationSource to apply CORS policies before requests reach the dispatch servlet. You can define a CorsFilter bean to integrate it into the application context.
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.util.Arrays;
import java.util.Collections;
@Configuration
public class CorsFilterConfig {
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOrigins(Arrays.asList("http://localhost:4200", "http://another-domain.com"));
config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
config.setAllowedHeaders(Collections.singletonList("*"));
config.setMaxAge(3600L);
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
Key CORS Parameters
- origins: Specifies a list of allowed origin domains. Use "*" for all, but be cautious with production environments as it can be a security risk.
- methods: Defines the HTTP methods allowed for cross-origin requests (e.g., "GET", "POST", "PUT", "DELETE", "OPTIONS").
- headers: Lists the request headers allowed in a cross-origin request. "*" allows all.
- exposedHeaders: Specifies which headers, beyond the simple response headers, are safe to expose to the browser.
- allowCredentials: Set to
trueto allow the browser to send cookies, HTTP authentication, and client-side SSL certificates with the request. - maxAge: Indicates how long the results of a preflight request can be cached by the client (in seconds). This reduces the number of preflight requests.
Preflight Requests
For "non-simple" requests (e.g., PUT, DELETE, or POST with custom headers or non-standard content types), browsers send an OPTIONS HTTP request, known as a "preflight" request, before the actual request. This preflight request checks with the server if the actual request is safe to send. Spring Boot automatically handles these OPTIONS requests based on your CORS configuration, responding with the appropriate CORS headers.
Conclusion
Spring Boot provides a comprehensive and easy-to-use set of tools for managing CORS. Whether you need a broad global policy, fine-grained control for specific endpoints, or advanced programmatic configuration, Spring Boot offers flexible solutions to ensure secure and functional cross-origin communication in your applications. Choose the approach that best fits the granularity and complexity of your application's requirements.