Mastering CORS in Spring: 5 Ways to Enable Cross‑Origin Requests

This article explains why browsers enforce the same‑origin policy, defines cross‑origin requests, outlines the restrictions of non‑same‑origin interactions, and presents five practical methods—including a global CorsFilter, WebMvcConfigurer, @CrossOrigin annotation, manual header setting, and a custom filter—to implement CORS in Java Spring backends.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Mastering CORS in Spring: 5 Ways to Enable Cross‑Origin Requests

Why CORS Issues Occur

The browser enforces a same‑origin policy . A script can only read cookies, local storage, IndexedDB, or make AJAX calls to resources that share the same protocol, host, and port as the page that loaded the script. When a request targets a different origin, the browser blocks the response unless the server explicitly permits the cross‑origin access via CORS headers.

What Constitutes a Cross‑Origin Request

A request is cross‑origin when any of the three components—protocol, domain, or port—differs from those of the page that initiated the request.

Restrictions Imposed by the Same‑Origin Policy

Scripts cannot read cookies, LocalStorage, or IndexedDB belonging to another origin.

Scripts cannot access the DOM of a page served from a different origin.

Scripts cannot send AJAX (XHR/fetch) requests to a different origin unless the server returns the appropriate CORS response headers.

Five Common Ways to Enable CORS in a Spring‑based Java Backend

Register a global CorsFilter bean.

Implement WebMvcConfigurer and override addCorsMappings.

Apply the @CrossOrigin annotation on controller classes or individual handler methods.

Manually add the required headers via HttpServletResponse.

Create a custom servlet filter that sets the CORS headers and configure it in web.xml.

1. Global CorsFilter Bean

@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        // 1. Define the CORS policy
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("*");               // allow any origin
        config.setAllowCredentials(true);            // include cookies
        config.addAllowedMethod("*");               // allow all HTTP methods
        config.addAllowedHeader("*");               // allow all request headers
        config.addExposedHeader("*");               // expose all response headers

        // 2. Map the policy to URL patterns
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);

        // 3. Return the filter instance
        return new CorsFilter(source);
    }
}

2. Override WebMvcConfigurer

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowCredentials(true)
                .allowedOrigins("*")
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowedHeaders("*")
                .exposedHeaders("*");
    }
}

3. Use @CrossOrigin Annotation (Local CORS)

On a controller class (applies to all handler methods):

@RestController
@CrossOrigin(origins = "*")
public class HelloController {
    @RequestMapping("/hello")
    public String hello() {
        return "hello world";
    }
}

On a single method (more granular control):

@RequestMapping("/hello")
@CrossOrigin(origins = "*")
public String hello() {
    return "hello world";
}

4. Manually Set Response Headers (Local CORS)

@RequestMapping("/index")
public String index(HttpServletResponse response) {
    response.addHeader("Access-Control-Allow-Origin", "*");
    // Optional: add other CORS headers such as Access-Control-Allow-Methods, etc.
    return "index";
}

5. Custom Servlet Filter Implementation (Local CORS)

Define a filter class that adds the required CORS headers to every response.

package com.mesnac.aop;

import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;

@Component
public class MyCorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type");
        chain.doFilter(req, res);
    }
    @Override public void init(FilterConfig filterConfig) {}
    @Override public void destroy() {}
}

Configure the filter in web.xml (the XML tags are escaped so they are not parsed as HTML):

<!-- CORS START -->
<filter>
    <filter-name>CorsFilter</filter-name>
    <filter-class>com.mesnac.aop.MyCorsFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CorsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<!-- CORS END -->

Key Takeaways

All approaches ultimately add the required Access-Control-* response headers so that browsers accept cross‑origin responses.

Global configurations ( CorsFilter bean, WebMvcConfigurer) affect every endpoint, while @CrossOrigin, manual header setting, and custom filters can be scoped to specific controllers or methods.

Spring MVC 4.2+ (Spring Boot 1.3+) is required for the built‑in CORS support.

When both global and local CORS settings are present, the more specific (local) configuration overrides the global one.

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.

BackendJavaspringCORSCross-OriginfilterWebMvcConfigurer
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

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.