docs
Cross-Origin Resource Sharing (CORS) support for enabling cross-origin requests with fine-grained control over allowed origins, methods, headers, and credentials.
Enables Cross-Origin Resource Sharing on annotated controllers or handler methods.
/**
* Marks the annotated handler method or class as supporting cross-origin requests.
*
* By default all origins and headers are allowed, credentials are not allowed, and
* the maximum age is set to 1800 seconds (30 minutes). The list of HTTP methods is
* set to the methods on the @RequestMapping if any, or to GET otherwise.
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {
/**
* Alias for {@link #origins}.
*/
@AliasFor("origins")
String[] value() default {};
/**
* List of allowed origins.
* These values are placed in the Access-Control-Allow-Origin header of both the
* pre-flight and actual responses.
* "*" means all origins are allowed.
* If undefined, all origins are allowed.
*/
@AliasFor("value")
String[] origins() default {};
/**
* Alternative to {@link #origins} that supports more flexible origin patterns.
* In contrast to {@link #origins} which only supports "*" and concrete origins,
* origin patterns are more flexible, e.g. "https://*.example.com" matches
* "https://www.example.com" and "https://foo.example.com".
*/
String[] originPatterns() default {};
/**
* List of request headers that can be used during the actual request.
* This property controls the value of the pre-flight response's
* Access-Control-Allow-Headers header.
* "*" means all headers requested by the client are allowed.
* If undefined, all requested headers are allowed.
*/
String[] allowedHeaders() default {};
/**
* List of response headers that the user-agent will allow the client to access.
* This property controls the value of actual response's Access-Control-Expose-Headers header.
* If undefined, an empty exposed header list is used.
*/
String[] exposedHeaders() default {};
/**
* List of supported HTTP request methods.
* If undefined, methods are set to the methods on the @RequestMapping,
* or to GET if not specified.
*/
RequestMethod[] methods() default {};
/**
* Whether the browser should send credentials, such as cookies along with
* cross domain requests, to the annotated endpoint.
* The configured value is set on the Access-Control-Allow-Credentials response header.
* NOTE: Be aware that this option establishes a high level of trust with the
* configured domains and also increases the surface attack of the web application
* by exposing sensitive user-specific information such as cookies and CSRF tokens.
* If undefined, credentials are not allowed.
*/
String allowCredentials() default "";
/**
* The maximum age (in seconds) of the cache duration for pre-flight responses.
* This property controls the value of the Access-Control-Max-Age response header.
* Setting this to a reasonable value can reduce the number of pre-flight request/response
* interactions required by the browser.
* A negative value means undefined.
* If undefined, max age is set to 1800 seconds (30 minutes).
*/
long maxAge() default -1;
}Usage Example:
@RestController
@RequestMapping("/api/products")
@CrossOrigin(origins = "http://localhost:3000")
public class ProductController {
@GetMapping
public List<Product> getAllProducts() {
return productService.findAll();
}
// Override CORS for specific method
@PostMapping
@CrossOrigin(
origins = {"http://localhost:3000", "https://example.com"},
methods = {RequestMethod.POST, RequestMethod.OPTIONS},
allowedHeaders = {"Content-Type", "Authorization"},
exposedHeaders = {"X-Total-Count"},
allowCredentials = "true",
maxAge = 3600
)
public Product createProduct(@RequestBody Product product) {
return productService.save(product);
}
// Allow all origins for specific endpoint
@GetMapping("/public/{id}")
@CrossOrigin(origins = "*")
public Product getPublicProduct(@PathVariable Long id) {
return productService.findById(id);
}
}
// CORS on class level
@RestController
@RequestMapping("/api/public")
@CrossOrigin(
originPatterns = "https://*.example.com",
methods = {RequestMethod.GET, RequestMethod.POST},
maxAge = 3600
)
public class PublicApiController {
@GetMapping("/data")
public Data getData() {
return dataService.getPublicData();
}
}Configuration object for CORS that can be used programmatically.
/**
* A container for CORS configuration along with methods to check against the
* actual origin, HTTP methods, and headers of a given request.
*
* By default a newly created CorsConfiguration does not permit any cross-origin
* requests and must be configured explicitly to indicate what should be allowed.
*/
public class CorsConfiguration {
/**
* Wildcard representing all origins, methods, or headers.
*/
public static final String ALL = "*";
/**
* Create a new CorsConfiguration.
*/
public CorsConfiguration() {}
/**
* Create a deep copy of the given CorsConfiguration.
*
* @param other the CorsConfiguration to copy
*/
public CorsConfiguration(CorsConfiguration other) {}
/**
* Set the origins to allow, e.g. "http://domain1.com".
* The special value "*" allows all domains.
* By default this is not set.
*
* @param origins the origins to allow
*/
public void setAllowedOrigins(List<String> origins) {}
/**
* Return the configured origins to allow, or null if none.
*
* @return the allowed origins
*/
public List<String> getAllowedOrigins() {}
/**
* Add an origin to allow.
*
* @param origin the origin to add
*/
public void addAllowedOrigin(String origin) {}
/**
* Alternative to setAllowedOrigins that supports more flexible patterns
* for specifying the origins for which cross-origin requests are allowed.
*
* @param originPatterns the origin patterns to allow
*/
public void setAllowedOriginPatterns(List<String> originPatterns) {}
/**
* Return the configured origin patterns to allow, or null if none.
*
* @return the allowed origin patterns
*/
public List<String> getAllowedOriginPatterns() {}
/**
* Add an origin pattern to allow.
*
* @param originPattern the origin pattern to add
*/
public void addAllowedOriginPattern(String originPattern) {}
/**
* Set the HTTP methods to allow, e.g. "GET", "POST", etc.
* The special value "*" allows all methods.
* If not set, only "GET" and "HEAD" are allowed.
* By default this is not set.
*
* @param methods the HTTP methods to allow
*/
public void setAllowedMethods(List<String> methods) {}
/**
* Return the allowed HTTP methods, or null in which case only "GET" and "HEAD" allowed.
*
* @return the allowed methods
*/
public List<String> getAllowedMethods() {}
/**
* Add an HTTP method to allow.
*
* @param method the HTTP method to add
*/
public void addAllowedMethod(HttpMethod method) {}
/**
* Add an HTTP method to allow.
*
* @param method the HTTP method to add
*/
public void addAllowedMethod(String method) {}
/**
* Set the list of headers that a pre-flight request can list as allowed
* for use during an actual request.
* The special value "*" allows actual requests to send any header.
* A header name is not required to be listed if it is one of:
* Cache-Control, Content-Language, Expires, Last-Modified, or Pragma.
* By default this is not set.
*
* @param headers the headers to allow
*/
public void setAllowedHeaders(List<String> headers) {}
/**
* Return the allowed actual request headers, or null if none.
*
* @return the allowed headers
*/
public List<String> getAllowedHeaders() {}
/**
* Add an actual request header to allow.
*
* @param header the header to add
*/
public void addAllowedHeader(String header) {}
/**
* Set the list of response headers other than simple headers (i.e. Cache-Control,
* Content-Language, Content-Type, Expires, Last-Modified, or Pragma) that an
* actual response might have and can be exposed.
* The special value "*" allows all headers to be exposed.
* By default this is not set.
*
* @param headers the headers to expose
*/
public void setExposedHeaders(List<String> headers) {}
/**
* Return the configured response headers to expose, or null if none.
*
* @return the exposed headers
*/
public List<String> getExposedHeaders() {}
/**
* Add a response header to expose.
* The special value "*" allows all headers to be exposed.
*
* @param header the header to expose
*/
public void addExposedHeader(String header) {}
/**
* Whether user credentials are supported.
* By default this is not set (i.e. user credentials are not supported).
*
* @param allowCredentials whether to allow credentials
*/
public void setAllowCredentials(Boolean allowCredentials) {}
/**
* Return the configured allowCredentials flag, or null if none.
*
* @return whether credentials are allowed
*/
public Boolean getAllowCredentials() {}
/**
* Configure how long, in seconds, the response from a pre-flight request
* can be cached by clients.
* By default this is not set.
*
* @param maxAge the max age in seconds
*/
public void setMaxAge(Long maxAge) {}
/**
* Return the configured maxAge value, or null if none.
*
* @return the max age
*/
public Long getMaxAge() {}
/**
* Check the origin of the request against the configured allowed origins.
*
* @param requestOrigin the origin to check
* @return the origin to use for the response, or null which means the
* request origin is not allowed
*/
public String checkOrigin(String requestOrigin) {}
/**
* Check the HTTP method of the request against the configured allowed methods.
*
* @param requestMethod the HTTP method to check
* @return the HTTP methods to list in the response of a pre-flight request,
* or null if the supplied requestMethod is not allowed
*/
public List<HttpMethod> checkHttpMethod(HttpMethod requestMethod) {}
/**
* Check the supplied request headers against the configured allowed headers.
*
* @param requestHeaders the request headers to check
* @return the list of allowed headers to list in the response of a pre-flight
* request, or null if none of the supplied request headers is allowed
*/
public List<String> checkHeaders(List<String> requestHeaders) {}
/**
* Combine this configuration with another.
*
* @param other the other CorsConfiguration to combine with
* @return the combined CorsConfiguration
*/
public CorsConfiguration combine(CorsConfiguration other) {}
}Usage Example:
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000", "https://example.com")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.exposedHeaders("Authorization", "X-Total-Count")
.allowCredentials(true)
.maxAge(3600);
}
};
}
// Programmatic CorsConfiguration
@Bean
public CorsConfiguration apiCorsConfiguration() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOriginPatterns(List.of("https://*.example.com"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
config.setAllowedHeaders(List.of("*"));
config.setExposedHeaders(List.of("X-Total-Count", "X-Page-Number"));
config.setAllowCredentials(true);
config.setMaxAge(3600L);
return config;
}
}Assists with the registration of CorsConfiguration mapped to a path pattern.
/**
* Assists with the registration of global, URL pattern based CorsConfiguration mappings.
*/
public class CorsRegistry {
/**
* Enable cross-origin request handling for the specified path pattern.
* Exact path mapping URIs (such as "/admin") are supported as well as
* Ant-style path patterns (such as "/admin/**").
*
* @param pathPattern the path pattern to map to
* @return a CorsRegistration for further configuration
*/
public CorsRegistration addMapping(String pathPattern) {}
/**
* Return the registered CorsConfiguration objects.
*
* @return a Map with path patterns as keys and CorsConfiguration objects as values
*/
protected Map<String, CorsConfiguration> getCorsConfigurations() {}
}Usage Example:
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// API endpoints
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("Content-Type", "Authorization")
.exposedHeaders("X-Total-Count")
.allowCredentials(true)
.maxAge(3600);
// Public endpoints
registry.addMapping("/public/**")
.allowedOriginPatterns("*")
.allowedMethods("GET")
.maxAge(86400);
// Admin endpoints - more restrictive
registry.addMapping("/admin/**")
.allowedOrigins("https://admin.example.com")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(1800);
}
}Assists with the creation of a CorsConfiguration instance for a given path pattern.
/**
* Assists with the creation of a CorsConfiguration instance for a given URL path pattern.
*/
public class CorsRegistration {
/**
* Set the origins to allow. The special value "*" allows all domains.
*
* @param origins the origins to allow
* @return this CorsRegistration for chaining
*/
public CorsRegistration allowedOrigins(String... origins) {}
/**
* Set the origin patterns to allow. Unlike origins, patterns are more
* flexible, e.g. "https://*.example.com".
*
* @param patterns the origin patterns to allow
* @return this CorsRegistration for chaining
*/
public CorsRegistration allowedOriginPatterns(String... patterns) {}
/**
* Set the HTTP methods to allow. The special value "*" allows all methods.
*
* @param methods the HTTP methods to allow
* @return this CorsRegistration for chaining
*/
public CorsRegistration allowedMethods(String... methods) {}
/**
* Set the list of headers that a pre-flight request can list as allowed
* for use during an actual request. The special value "*" allows all headers.
*
* @param headers the headers to allow
* @return this CorsRegistration for chaining
*/
public CorsRegistration allowedHeaders(String... headers) {}
/**
* Set the list of response headers that an actual response might have and
* can be exposed. The special value "*" allows all headers.
*
* @param headers the headers to expose
* @return this CorsRegistration for chaining
*/
public CorsRegistration exposedHeaders(String... headers) {}
/**
* Whether user credentials are supported.
*
* @param allowCredentials whether to allow credentials
* @return this CorsRegistration for chaining
*/
public CorsRegistration allowCredentials(boolean allowCredentials) {}
/**
* Configure how long, in seconds, the response from a pre-flight request
* can be cached by clients.
*
* @param maxAge the max age in seconds
* @return this CorsRegistration for chaining
*/
public CorsRegistration maxAge(long maxAge) {}
/**
* Apply the configured CorsConfiguration and return it.
*
* @return the CorsConfiguration
*/
protected CorsConfiguration getCorsConfiguration() {}
}