Access-Control-Allow-Origin: * allows any website to access your resources. Always specify exact origins in production.
Apache Tomcat includes built-in support for CORS via the CorsFilter (available since Tomcat 7.0.41). Configure it in your application's web.xml file.
Allow a single trusted origin:
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>https://example.com</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,Authorization,X-Requested-With</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
Allow multiple specific origins (issue #146):
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<!-- Comma-separated list of allowed origins -->
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>https://example.com,https://app.example.com,https://staging.example.com</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,Authorization</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
When using cookies or authentication:
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>https://example.com</param-value>
</init-param>
<!-- Enable credentials (cookies, HTTP auth) -->
<init-param>
<param-name>cors.support.credentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
Full configuration with all common parameters:
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<!-- Allowed origins -->
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>https://example.com,https://app.example.com</param-value>
</init-param>
<!-- Allowed HTTP methods -->
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
</init-param>
<!-- Allowed request headers -->
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,Authorization,X-Requested-With</param-value>
</init-param>
<!-- Exposed response headers (visible to client) -->
<init-param>
<param-name>cors.exposed.headers</param-name>
<param-value>Content-Length,X-Custom-Header</param-value>
</init-param>
<!-- Allow credentials (cookies, HTTP auth) -->
<init-param>
<param-name>cors.support.credentials</param-name>
<param-value>true</param-value>
</init-param>
<!-- Preflight cache duration (seconds) -->
<init-param>
<param-name>cors.preflight.maxage</param-name>
<param-value>86400</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
Allow any subdomain of example.com using regex:
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<!-- Use regex to match origins -->
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.origins.regex</param-name>
<param-value>https?://(.+\.)?example\.com</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
Apply different CORS policies to different paths:
<!-- Restricted CORS for API endpoints -->
<filter>
<filter-name>ApiCorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>https://example.com</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>ApiCorsFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
<!-- Open CORS for public endpoints -->
<filter>
<filter-name>PublicCorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.origins</param-name>
<param-value>*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>PublicCorsFilter</filter-name>
<url-pattern>/public/*</url-pattern>
</filter-mapping>
| Parameter | Description | Default |
|---|---|---|
cors.allowed.origins |
Comma-separated allowed origins | * (any) |
cors.allowed.origins.regex |
Regex pattern for origins | None |
cors.allowed.methods |
Allowed HTTP methods | GET,POST,HEAD,OPTIONS |
cors.allowed.headers |
Request headers allowed | * |
cors.exposed.headers |
Response headers exposed to client | None |
cors.support.credentials |
Enable credentials | false |
cors.preflight.maxage |
Preflight cache (seconds) | 1800 (30 min) |
Important: CORS filter should be placed early in the filter chain, before authentication/authorization filters, so that preflight OPTIONS requests don't get rejected.
For full documentation, see:
For comprehensive testing instructions including curl commands, browser DevTools usage, and troubleshooting common CORS errors, see the CORS Testing Guide.
The content on this site stays fresh thanks to help from users like you! If you have suggestions or would like to contribute, fork us on GitHub.
Save 39% on CORS in Action with promotional code hossainco at manning.com/hossain