CORS in Spring Boot — Configuring Cross-Origin with @CrossOrigin Annotation
In this tutorial, you will learn about CORS in Spring Boot. We cover key concepts, practical examples, and best practices to help you master this topic.
Spring Boot provides multiple ways to configure CORS: the @CrossOrigin annotation for per-endpoint control, WebMvcConfigurer for global configuration, and WebFlux support for reactive applications.
What You'll Learn
- Using @CrossOrigin annotation on controllers
- Global CORS configuration with WebMvcConfigurer
- CORS for reactive Spring WebFlux
Why It Matters
Spring Boot powers many enterprise Java APIs. Proper CORS configuration enables secure cross-origin access for web frontends while maintaining Spring's security model. DodaTech's enterprise threat management API uses Spring Boot with globally configured CORS.
flowchart TD
A["Spring Boot API"] --> B{"Configuration approach"}
B -->|"Annotation"| C["@CrossOrigin on controller"]
B -->|"Global"| D["WebMvcConfigurer bean"]
B -->|"Reactive"| E["WebFlux config"]
C --> F["Works for specific endpoints"]
D --> G["Works for all endpoints"]
E --> H["Works for reactive stack"]
Code Examples
// Per-controller @CrossOrigin annotation
@RestController
@RequestMapping("/api/public")
@CrossOrigin(origins = "*")
public class PublicController {
@GetMapping("/data")
public Map<String, String> getData() {
return Map.of("message", "public data");
}
}
// Specific endpoint with restricted origin
@RestController
@RequestMapping("/api/admin")
public class AdminController {
@CrossOrigin(origins = "https://admin.example.com")
@DeleteMapping("/users/{id}")
public Map<String, String> deleteUser(@PathVariable String id) {
return Map.of("deleted", id);
}
}
// Global CORS configuration via WebMvcConfigurer
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins(
"https://app.example.com",
"https://admin.example.com"
)
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("Content-Type", "Authorization")
.exposedHeaders("X-RateLimit-Remaining")
.allowCredentials(true)
.maxAge(3600);
}
}
// WebFlux reactive CORS configuration
@Configuration
public class ReactiveCorsConfig implements WebFluxConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://app.example.com")
.allowedMethods("GET", "POST")
.allowCredentials(true);
}
}
# Test Spring Boot CORS
curl -I -H "Origin: https://admin.example.com" \
http://localhost:8080/api/admin/users/1 \
-X DELETE | grep -i "access-control"
Common Mistakes
1. Forgetting Spring Security CORS Configuration
Spring Security blocks CORS preflight by default. Add .cors() to the security filter chain.
2. Mixing @CrossOrigin and Global Config
The @CrossOrigin annotation on a method overrides the global config for that method.
3. Not Allowing OPTIONS in Spring Security
Preflight OPTIONS requests must pass through security without authentication.
4. Using Origins with Trailing Slashes
Origins should not have trailing slashes. "https://example.com/" is invalid.
5. Setting allowCredentials to True Without Specific Origins
Same restriction: credentials require specific origins, not wildcard.
Practice Questions
- What annotation enables CORS on a Spring controller?
- How do you configure global CORS in Spring Boot?
- What configuration is needed for Spring Security to work with CORS?
- How does WebFlux CORS configuration differ from MVC?
- Can you combine @CrossOrigin with WebMvcConfigurer?
Answers:
- @CrossOrigin.
- Implement WebMvcConfigurer and override addCorsMappings.
- Add .cors() to the HttpSecurity configuration.
- WebFlux uses CorsRegistry in WebFluxConfigurer instead of WebMvcConfigurer.
- Yes. @CrossOrigin on specific methods overrides the global configuration.
Challenge: Build a Spring Boot API with three security tiers (public, authenticated, admin). Implement global CORS for public endpoints and annotation-based CORS for admin endpoints. Configure Spring Security to allow OPTIONS preflight without authentication.
FAQ
Mini Project
Build a Spring Boot API with microservice architecture: a gateway service with CORS configuration, multiple backend services, and a React frontend. Implement Spring Security with JWT authentication and CORS. Add integration tests using TestRestTemplate with custom Origin headers.
What's Next
Explore Flask CORS configuration using flask-cors, then learn NGINX CORS configuration for reverse proxy setups.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro