Mastering CORS in Spring MVC: Practical Configurations & Annotations

Spring MVC provides built‑in CORS support, allowing you to configure preflight, simple, and actual requests via global HandlerMapping settings, @CrossOrigin annotations, Java‑based CorsRegistry, or CorsFilter, with detailed options for origins, headers, methods, credentials, and max‑age to secure cross‑origin interactions.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering CORS in Spring MVC: Practical Configurations & Annotations

Overview

Spring MVC allows handling of CORS (Cross‑Origin Resource Sharing). For security, browsers block AJAX calls to resources on a different origin, preventing scripts from other sites from using your credentials.

CORS is a W3C specification implemented by most browsers, enabling you to specify which cross‑origin requests are authorized instead of using less secure solutions like IFRAME or JSONP.

Solution

The CORS specification distinguishes preflight requests, simple requests, and actual requests. Spring MVC’s HandlerMapping provides built‑in support. After a request is mapped to a handler, HandlerMapping checks the CORS configuration and processes the request accordingly. Preflight requests are handled directly; simple and actual requests are intercepted, validated, and the appropriate CORS response headers are set.

To enable cross‑origin requests (i.e., when an Origin header is present and differs from the request host), you must declare CORS configuration explicitly. If no matching configuration is found, the preflight request is rejected and CORS headers are omitted from simple and actual responses.

Each HandlerMapping can be associated with a URL‑pattern‑based CorsConfiguration. Typically applications declare these mappings globally via MVC Java Config or XML namespace, applying a single global mapping to all HandlerMapping instances.

Global HandlerMapping‑level CORS settings can be combined with finer‑grained controller‑level configurations. Controllers can use @CrossOrigin at class or method level, or implement CorsConfigurationSource for custom handling.

When both global and local configurations are present, the local values usually override the global ones for attributes that accept a single value, such as allowCredentials and maxAge.

@CrossOrigin Annotation

The @CrossOrigin annotation enables cross‑origin requests on annotated controller methods. Example:

@RestController
@RequestMapping("/account")
public class AccountController {
    @CrossOrigin
    @GetMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }
}

By default, @CrossOrigin allows all origins, all headers, and all HTTP methods mapped to the controller method.

allowCredentials is disabled by default because it exposes sensitive user‑specific information (cookies, CSRF tokens). When enabled, you must specify allowOrigins (cannot be "*") or allowOriginPatterns to match a dynamic set of origins.

maxAge defaults to 30 minutes.

@CrossOrigin can also be placed at the class level and is inherited by all methods, e.g.:

@CrossOrigin(origins = "https://pack.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
    @GetMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }
}

You can combine class‑level and method‑level @CrossOrigin annotations:

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
    @CrossOrigin("https://domain2.com")
    @GetMapping("/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }
}

Global CORS Configuration

Beyond fine‑grained controller settings, you may define global CORS configuration. You can set a URL‑based CorsConfiguration on any HandlerMapping, but most applications use MVC Java Config or XML namespace.

By default, global configuration enables all origins, all headers, and GET, HEAD, and POST methods. allowCredentials remains disabled for the same security reasons described above.

Programmatic Configuration

To enable CORS in MVC Java configuration, use CorsRegistry in a WebMvcConfigurer implementation:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
                .allowedOrigins("https://domain2.com")
                .allowedMethods("PUT", "DELETE")
                .allowedHeaders("header1", "header2", "header3")
                .exposedHeaders("header1", "header2")
                .allowCredentials(true)
                .maxAge(3600);
    }
}

Filter Configuration

CORS support can also be applied via the built‑in CorsFilter. When using Spring Security, remember that it already provides CORS support.

Configure the filter by supplying a CorsConfigurationSource:

CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("https://domain1.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);

CorsFilter filter = new CorsFilter(source);

Done!

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaBackend DevelopmentCORSCross-OriginWeb SecuritySpring MVC
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.