Mastering CORS in Spring Boot: Simple Configurations to Eliminate Cross‑Origin Errors

This article explains the Same Origin Policy, introduces the CORS standard, details simple and preflight request handling, lists essential response headers, and provides three practical Spring Boot solutions—including global configuration, a servlet filter, and the @CrossOrigin annotation—to resolve cross‑origin issues.

macrozheng
macrozheng
macrozheng
Mastering CORS in Spring Boot: Simple Configurations to Eliminate Cross‑Origin Errors

Front‑back separation makes CORS a common problem; this guide shows how to solve it in Spring Boot.

Problem Background

Same Origin Policy (SOP) restricts client scripts to resources from the same protocol, host, and port. If any of these differ, the browser treats the request as cross‑origin and blocks it.

CORS Overview

CORS (Cross‑Origin Resource Sharing) is a W3C standard that allows browsers to make XMLHttpRequest or Fetch calls to a different origin when the server explicitly permits it. The browser adds the necessary headers automatically; the server must implement the CORS interface.

Browsers classify CORS requests into simple requests and non‑simple (preflight) requests.

Simple vs Non‑Simple Requests

Simple requests (GET, HEAD, POST) with only the following headers are sent directly with an Origin header:

Accept

Accept‑Language

Content‑Language

Last‑Event‑ID

Content‑Type (only application/x-www-form-urlencoded, multipart/form-data, or text/plain)

Any request that does not meet these criteria triggers a preflight OPTIONS request, where the browser asks the server which methods and headers are allowed.

Response Headers

Access-Control-Allow-Origin : required; either the request’s Origin value or * to allow any domain.

Access-Control-Allow-Methods : required; a comma‑separated list (or *) of HTTP methods the server supports.

Access-Control-Expose-Headers : optional; lists additional response headers that JavaScript can read.

Access-Control-Allow-Credentials : optional; boolean indicating whether cookies may be sent.

Access-Control-Max-Age : optional; caches the preflight response for the given number of seconds.

If you notice an OPTIONS request for every call, configure Access-Control-Max-Age to reduce preflight traffic.

Solutions

Method 1: Global configuration with WebMvcConfigurer

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 CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                .allowCredentials(true)
                .maxAge(3600)
                .allowedHeaders("*");
    }
}

Older tutorials use the now‑deprecated WebMvcConfigurerAdapter; with Spring 5 you can implement WebMvcConfigurer directly.

Method 2: Servlet filter

import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter(filterName = "CorsFilter")
@Configuration
public class CorsFilter 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-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        chain.doFilter(req, res);
    }
}

This approach writes the necessary headers directly into the response; only one of the first two methods is needed.

Method 3: @CrossOrigin annotation

public class GoodsController {
    @CrossOrigin(origins = "http://localhost:4000")
    @GetMapping("goods-url")
    public Response queryGoodsWithGoodsUrl(@RequestParam String goodsUrl) throws Exception {}
}

The annotation can be placed on a class or method, giving fine‑grained control over CORS for individual endpoints.

All three methods are valid; the one closest to the request (e.g., method‑level annotation) takes precedence, similar to CSS specificity.

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.

BackendSpring BootHTTPWeb DevelopmentCORSCross-Origin
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

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.