Spring CORS No 'Access-Control-Allow-Origin' header is present
SpringSpring MvcCorsSpring Problem Overview
I am getting the following problem after porting web.xml to java config
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access.
Based on a few Spring references, the following attempt has been tried:
@Configuration
@ComponentScan(basePackageClasses = AppConfig.class, useDefaultFilters = false, includeFilters = {
@Filter(org.springframework.stereotype.Controller.class) })
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/*").allowedOrigins("*").allowedMethods("GET", "POST", "OPTIONS", "PUT")
.allowedHeaders("Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method",
"Access-Control-Request-Headers")
.exposedHeaders("Access-Control-Allow-Origin", "Access-Control-Allow-Credentials")
.allowCredentials(true).maxAge(3600);
}
}
The values chosen were taken from a working web.xml filter:
<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>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
</init-param>
<init-param>
<param-name>cors.exposed.headers</param-name>
<param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
</init-param>
<init-param>
<param-name>cors.support.credentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.preflight.maxage</param-name>
<param-value>10</param-value>
</init-param> </filter> <filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Any ideas why the Spring java config approach is not working like the web.xml file did?
Spring Solutions
Solution 1 - Spring
Change the CorsMapping from registry.addMapping("/*")
to registry.addMapping("/**")
in addCorsMappings
method.
Check out this Spring CORS Documentation .
From the documentation -
Enabling CORS for the whole application is as simple as:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
You can easily change any properties, as well as only apply this CORS configuration to a specific path pattern:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
}
Controller method CORS configuration
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
}
To enable CORS for the whole controller -
@CrossOrigin(origins = "http://domain2.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
You can even use both controller-level and method-level CORS configurations; Spring will then combine attributes from both annotations to create merged CORS configuration.
@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin("http://domain2.com")
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
Solution 2 - Spring
Helpful tip - if you're using Spring data rest you need a different approach.
@Component
public class SpringDataRestCustomization extends RepositoryRestConfigurerAdapter {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.getCorsRegistry().addMapping("/**")
.allowedOrigins("http://localhost:9000");
}
}
Solution 3 - Spring
We had the same issue and we resolved it using Spring's XML configuration as below:
Add this in your context xml file
<mvc:cors>
<mvc:mapping path="/**"
allowed-origins="*"
allowed-headers="Content-Type, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Authorization, X-Requested-With, requestId, Correlation-Id"
allowed-methods="GET, PUT, POST, DELETE"/>
</mvc:cors>
Solution 4 - Spring
Omkar's answer is quite comprehensive.
But some part of the Global config part has changed.
According to the spring boot 2.0.2.RELEASE reference
> As of version 4.2, Spring MVC supports CORS. Using controller method > CORS configuration with @CrossOrigin annotations in your Spring Boot > application does not require any specific configuration. Global CORS > configuration can be defined by registering a WebMvcConfigurer bean > with a customized addCorsMappings(CorsRegistry) method, as shown in > the following example:
@Configuration
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**");
}
};
}
}
Most answer in this post using WebMvcConfigurerAdapter
, however
https://stackoverflow.com/questions/47552835/the-type-webmvcconfigureradapter-is-deprecated
> Since Spring 5 you just need to implement the interface > WebMvcConfigurer: > > public class MvcConfig implements WebMvcConfigurer { > > This is because Java 8 introduced default methods on interfaces which > cover the functionality of the WebMvcConfigurerAdapter class
Solution 5 - Spring
Following on Omar's answer, I created a new class file in my REST API project called WebConfig.java
with this configuration:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*");
}
}
This allows any origin to access the API and applies it to all controllers in the Spring project.
Solution 6 - Spring
If you are using Spring Security ver >= 4.2 you can use Spring Security's native support instead of including Apache's:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
The example above was copied from a Spring blog post in which you also can find information about how to configure CORS on a controller, specific controller methods, etc. Moreover, there is also XML configuration examples as well as Spring Boot integration.
Solution 7 - Spring
as @Geoffrey pointed out, with spring security, you need a different approach as described here: https://stackoverflow.com/questions/40286549/spring-boot-security-cors
Solution 8 - Spring
public class TrackingSystemApplication {
public static void main(String[] args) {
SpringApplication.run(TrackingSystemApplication.class, args);
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:4200").allowedMethods("PUT", "DELETE",
"GET", "POST");
}
};
}
}
Solution 9 - Spring
If you want to allow all origins(*) then use setAllowedOriginPatterns instead of setAllowedOrigins
Could you please follow the below link
https://github.com/spring-projects/spring-framework/issues/26111
Solution 10 - Spring
I also had messages like No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access.
I had configured cors properly, but what was missing in webflux in RouterFuncion was accept and contenttype headers APPLICATION_JSON like in this piece of code:
@Bean
RouterFunction<ServerResponse> routes() {
return route(POST("/create")
.and(accept(APPLICATION_JSON))
.and(contentType(APPLICATION_JSON)), serverRequest -> create(serverRequest);
}
Solution 11 - Spring
For some reason, if still somebody not able to bypass CORS, write the header which browser wants to access your request.
Add this bean inside your configuration file.
@Bean
public WebSecurityConfigurerAdapter webSecurity() {
return new WebSecurityConfigurerAdapter() {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().addHeaderWriter(
new StaticHeadersWriter("Access-Control-Allow-Origin", "*"));
}
};
}
This way we can tell the browser we are allowing cross-origin from all origin. if you want to restrict from specific path then change the "*" to {'http://localhost:3000',""}.
Helpfull reference to understand this behaviour https://www.concretepage.com/spring-4/spring-4-rest-cors-integration-using-crossorigin-annotation-xml-filter-example
Solution 12 - Spring
I have found the solution in spring boot by using @CrossOrigin annotation.
@Configuration
@CrossOrigin
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
Solution 13 - Spring
This is how I fix Access-Control-Allow-Origin is present" problem after lots of hit and try and research.
After adding Spring security lots of developers face cross origin problem, this is the fix of that problem.
-
adding the definition of the custom filter class
public class CsrfTokenLogger implements Filter { private Logger logger = Logger.getLogger(CsrfTokenLogger.class.getName()); @Override public void doFilter( ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { Object o = request.getAttribute("_csrf"); CsrfToken token = (CsrfToken) o; filterChain.doFilter(request, response); } }
-
Adding the custom filter in the configuration class
@Configuration public class ProjectConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.addFilterAfter( new CsrfTokenLogger(), CsrfFilter.class) .authorizeRequests() .antMatchers("/login*").permitAll() .anyRequest().authenticated(); } }
Solution 14 - Spring
I solved this same problem in this way. Basically adding this @EnableWebSecurity
annotation and adding protected void configure(HttpSecurity http) throws Exception {}
Change from this:
@Configuration
public class WebConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*");
}
};
}
}
to this
@Configuration
@EnableWebSecurity
public class WebConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests().antMatchers("/**").permitAll().anyRequest().authenticated();
http.cors().and().csrf().disable();
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*");
}
};
}
}
Solution 15 - Spring
reversebind was correct in his answer that Spring Data Rest does indeed have a different approach. However I couldn't get the code sample they provided to work as I couldn't import RepositoryRestConfigurerAdapter. After digging through the documentation, I instead used this class which worked for me.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
@Configuration
class CustomRestMvcConfiguration {
@Bean
public RepositoryRestConfigurer repositoryRestConfigurer() {
return new RepositoryRestConfigurer() {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) {
cors.addMapping("/**")
.allowedOrigins("http://localhost:4200");
}
};
}
}