Cross-Origin Resource Sharing (CORS) is managed by setting specific HTTP response headers, primarily Access-Control-Allow-Origin, which dictates which external domains are permitted to access the resource. When a browser blocks a request due to CORS policy, the error typically resembles:
Access to XMLHttpRequest has been blocked by CORS policy: Response to preflight request doesn't pass access control check...
Here are the primary methods to enable CORS in a Java Spring environment.
1. Implementing a Servlet Filter
You can create a generic filter to intercept requests and manually inject CORS headers into the response.
Filter Implementation:
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CorsHandlerFilter implements Filter {
private FilterConfig filterConfig;
public void init(FilterConfig filterConfig) {
this.filterConfig = filterConfig;
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse httpRes = (HttpServletResponse) res;
String allowedOrigin = filterConfig.getInitParameter("AllowedOrigin");
String allowedMethods = filterConfig.getInitParameter("AllowedMethods");
String allowedHeaders = filterConfig.getInitParameter("AllowedHeaders");
String preflightMaxAge = filterConfig.getInitParameter("PreflightMaxAge");
httpRes.setHeader("Access-Control-Allow-Origin", allowedOrigin);
httpRes.setHeader("Access-Control-Allow-Methods", allowedMethods);
httpRes.setHeader("Access-Control-Allow-Headers", allowedHeaders);
httpRes.setHeader("Access-Control-Max-Age", preflightMaxAge);
chain.doFilter(req, res);
}
public void destroy() {
// Cleanup logic
}
}
Deployment Descriptor (web.xml) Configuration:
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>com.example.web.CorsHandlerFilter</filter-class>
<init-param>
<param-name>AllowedOrigin</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>AllowedMethods</param-name>
<param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
</init-param>
<init-param>
<param-name>AllowedHeaders</param-name>
<param-value>Content-Type, Authorization</param-value>
</init-param>
<init-param>
<param-name>PreflightMaxAge</param-name>
<param-value>1800</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
2. XML Configuration for Spring MVC
If you are using the Spring MVC framework, you can leverage the built-in <mvc:cors> namespace for cleaner configuration. This approach often resolevs issues where manual filters fail to handle complex request types (like POST with specific headers).
<mvc:cors>
<mvc:mapping path="/resources/**"
allowed-origins="https://client-app.com"
allowed-methods="GET, POST"
allowed-headers="Content-Type, X-Auth-Token"
exposed-headers="X-Custom-Header"
allow-credentials="true"
max-age="1800" />
</mvc:cors>
You can define multiple mappings to restrict access to specific paths or whtielist specific domains instead of using the wildcard *.
3. Java Configuration Class
For annotation-based Spring setups, defining a @Configuration class that implements WebMvcConfigurer is the standard approach.
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class GlobalCorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/v2/api/**")
.allowedOrigins("https://trusted-site.com", "https://another-trusted-site.com")
.allowedMethods("GET", "POST", "PATCH", "DELETE")
.allowedHeaders("Authorization", "Content-Type")
.allowCredentials(true)
.maxAge(3600);
}
}