google-site-verification: google61fe8ba583a51912.html
CORS Configuration in Spring Boot: A Complete Guide

Cross-Origin Resource Sharing (CORS) is a crucial security mechanism that allows or restricts resources requested from one domain to another domain. In Spring Boot applications, proper CORS configuration is essential for frontend applications to communicate with your backend API.

What is CORS?

CORS is a browser security feature that blocks requests from one origin to another unless the server explicitly allows it. This becomes important when your frontend (e.g., React app on http://localhost:3000) needs to access your backend API (e.g., Spring Boot on http://localhost:8080).

CORS Configuration Methods in Spring Boot

Method 1: Global CORS Configuration

Create a global CORS configuration that applies to all endpoints in your application.

import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; import java.util.Arrays; @Configuration public class CorsConfig { @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); // Allow credentials config.setAllowCredentials(true); // Allow specific origins config.setAllowedOriginPatterns(Arrays.asList( "http://localhost:3000", "http://localhost:4200", "https://mydomain.com" )); // Allow specific headers config.setAllowedHeaders(Arrays.asList( "Origin", "Content-Type", "Accept", "Authorization", "X-Requested-With" )); // Allow specific methods config.setAllowedMethods(Arrays.asList( "GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH" )); // Expose specific headers to the client config.setExposedHeaders(Arrays.asList( "Authorization", "Content-Disposition" )); // How long the response to preflight request can be cached (in seconds) config.setMaxAge(3600L); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } }

Method 2: Using WebMvcConfigurer (for Spring MVC)

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("/api/**") .allowedOriginPatterns("http://localhost:3000", "https://*.mydomain.com") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); registry.addMapping("/public/**") .allowedOriginPatterns("*") .allowedMethods("GET") .allowedHeaders("*") .maxAge(1800); } }

Method 3: Using WebFluxConfigurer (for Spring WebFlux)

import org.springframework.context.annotation.Configuration; import org.springframework.web.reactive.config.CorsRegistry; import org.springframework.web.reactive.config.WebFluxConfigurer; @Configuration public class WebFluxConfig implements WebFluxConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:3000") .allowedMethods("*") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); } }

Method 4: Controller-Level CORS Configuration

Apply CORS configuration to specific controllers or methods.

import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api/users") @CrossOrigin(origins = "http://localhost:3000", maxAge = 3600, allowCredentials = "true") public class UserController { @GetMapping @CrossOrigin(origins = {"http://localhost:3000", "https://admin.mydomain.com"}) public List<User> getUsers() { // Implementation return userService.getAllUsers(); } @PostMapping public User createUser(@RequestBody User user) { // Implementation return userService.createUser(user); } }

Method 5: Method-Level CORS with @CrossOrigin

@RestController @RequestMapping("/api/products") public class ProductController { @GetMapping @CrossOrigin(origins = "*") // Allow all origins for this endpoint public List<Product> getAllProducts() { return productService.getAllProducts(); } @PostMapping @CrossOrigin(origins = "http://localhost:3000", methods = RequestMethod.POST, allowedHeaders = {"Content-Type", "Authorization"}) public Product createProduct(@RequestBody Product product) { return productService.createProduct(product); } }

Application Properties Configuration

You can also configure CORS through application.properties or application.yml:

application.properties

# CORS configuration app.cors.allowed-origins=http://localhost:3000,https://mydomain.com app.cors.allowed-methods=GET,POST,PUT,DELETE,OPTIONS app.cors.allowed-headers=* app.cors.allow-credentials=true app.cors.max-age=3600

application.yml

app: cors: allowed-origins: - "http://localhost:3000" - "https://mydomain.com" allowed-methods: GET,POST,PUT,DELETE,OPTIONS allowed-headers: "*" allow-credentials: true max-age: 3600

Security-Specific CORS Configuration

When using Spring Security, configure CORS through security configuration:

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.web.cors.CorsConfigurationSource; @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .cors(cors -> cors.configurationSource(corsConfigurationSource())) .csrf(csrf -> csrf.disable()) // Often disabled for APIs .authorizeHttpRequests(authz -> authz .requestMatchers("/api/public/**").permitAll() .requestMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated() ); return http.build(); } @Bean public CorsConfigurationSource corsConfigurationSource() { // Return your CorsConfigurationSource implementation return new UrlBasedCorsConfigurationSource(); } }

Testing CORS Configuration

Create a test to verify your CORS configuration:

import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @SpringBootTest @AutoConfigureMockMvc public class CorsTest { @Autowired private MockMvc mockMvc; @Test public void testCorsHeaders() throws Exception { mockMvc.perform(options("/api/users") .header("Origin", "http://localhost:3000") .header("Access-Control-Request-Method", "GET")) .andExpect(status().isOk()) .andExpect(header().exists("Access-Control-Allow-Origin")) .andExpect(header().string("Access-Control-Allow-Origin", "http://localhost:3000")); } }

Common CORS Issues and Solutions

Issue 1: Preflight Request Failing

Solution: Ensure OPTIONS method is allowed and proper headers are set.

Issue 2: Credentials Not Working

Solution: Set allowCredentials(true) and use specific origins (not wildcard *).

Issue 3: Headers Not Exposed

Solution: Use setExposedHeaders() to expose custom headers to the client.

Issue 4: Multiple CORS Configurations

Solution: Be aware that method-level configurations override class-level, which override global configurations.

Best Practices

  1. Be Specific with Origins: Avoid using * for origins when credentials are required.
  2. Limit Exposed Headers: Only expose necessary headers to enhance security.
  3. Use Appropriate Max Age: Balance between performance and security.
  4. Environment-Specific Configuration: Use different CORS settings for development, testing, and production.
  5. Test Thoroughly: Verify CORS behavior across different browsers and scenarios.

This comprehensive CORS configuration guide ensures your Spring Boot application can securely handle cross-origin requests while maintaining proper security standards.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper