Mastering CORS in Spring: Simple Configurations to Solve Cross‑Origin Issues
This article explains the Same Origin Policy, introduces the CORS standard, details required response headers, and provides three practical Spring implementations—global config, filter, and annotation—to enable cross‑origin requests efficiently.
In modern front‑end/back‑end separation, cross‑origin requests are a common obstacle. The Same Origin Policy (SOP) restricts scripts to resources from the same protocol, host and port, and CORS (Cross‑Origin Resource Sharing) is the W3C standard that allows browsers to make cross‑origin XMLHttpRequest or Fetch calls when the server explicitly permits it.
Problem background
Same Origin Policy (SOP) is a security measure that blocks scripts loaded from one origin from accessing resources of another origin. An origin is defined by protocol, host and port; any difference makes the request cross‑origin.
CORS overview
CORS lets browsers send cross‑origin requests by adding an Origin header. The browser classifies requests as simple or non‑simple. Simple requests (GET, HEAD, POST with limited headers) are sent directly with the Origin header. Non‑simple requests trigger a preflight OPTIONS request to verify allowed methods, headers and credentials.
Response headers
Access-Control-Allow-Origin – required; specifies allowed origin or *
Access-Control-Allow-Methods – required; comma‑separated list of HTTP methods the server permits
Access-Control-Expose-Headers – optional; lists additional response headers accessible to JavaScript
Access-Control-Allow-Credentials – optional; true to allow cookies
Access‑Control‑Max‑Age – optional; seconds the preflight result can be cached
Solutions
Three typical ways to enable CORS in a Spring application:
1. Global configuration via 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("*");
}
}2. Filter‑based approach
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);
}
}3. Annotation‑based on controller or method
public class GoodsController {
@CrossOrigin(origins = "http://localhost:4000")
@GetMapping("goods-url")
public Response queryGoodsWithGoodsUrl(@RequestParam String goodsUrl) throws Exception { }
}All three methods achieve the same effect; the one that is closest to the target (controller, filter, or global config) takes precedence, similar to CSS specificity. Choose the approach that best fits your project’s architecture.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
