Spring CORS No 'Access-Control-Allow-Origin' header is present
Asked Answered
S

18

114

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?

Sevenfold answered 29/1, 2016 at 18:28 Comment(0)
G
148

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) {
        // ...
    }
}
Ginoginsberg answered 29/1, 2016 at 19:0 Comment(8)
Enabling CORS for the whole application doesn't work for me.Biotite
Using addCorsMapping didn't work for me, tempted to say it's because of spring security..., however adding a corsConfigurationSource bean as suggested here solved my issue.Conjugate
At first this solution did not seem to work for me because the server didn't return either of Access Control header that Chrome requires. But then I found that another of my filters was rejecting OPTION requests before the CorsFilter saw them. Once I fixed the other filter, the CorsFilter added the correct headers to make Chrome happy.Risotto
Also should not forget to allow all clients registry.addMapping("/**").allowedOrigins("*"); spring.io/guides/gs/rest-service-corsLubricate
you're truly a lifesaver. I'm using Spring 4.2 and tried countless other alternatives and they all simply doesn't work until I tried the addCorsMappings override way. May or may not helped is added the standard CORS header as well as Access-Control-Allow-HeadersValrievalry
Its 2020, and spring boot annotation still doesn't work.Renfrow
You saved me) "Enabling CORS for the whole application is as simple as" - it works with spring boot "2.2.6.RELEASE" without spring security.Haircut
Enabling CORS for the whole application worked for me (using spring boot 2.4.2). Thanks :)Indifference
F
21

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");
  }
}
Flirtation answered 2/1, 2018 at 6:2 Comment(2)
Thanks for this post. I was kinda loosing hope when I noticed your post saying that Spring Data REST uses a different approach. Totally works for me now !Alcides
RepositoryRestConfigurerAdapter is deprecated. Just implements RepositoryRestConfigurer directly.Cenotaph
F
16

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

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

Fast answered 5/9, 2018 at 1:30 Comment(0)
S
13

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>
Sonia answered 7/2, 2017 at 15:56 Comment(0)
Q
8

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.

Quentin answered 10/5, 2018 at 11:51 Comment(0)
C
6

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.

Chromatography answered 29/1, 2016 at 18:55 Comment(0)
L
4

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

Legend answered 30/8, 2019 at 9:4 Comment(0)
K
4
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");
            }
        };
    }

}
Kerek answered 30/6, 2020 at 11:31 Comment(1)
WebMvcConfigurerAdapter is deprecated.Dragging
K
4

It works for me:

Spring Boot 3.1.1:

@Configuration
@EnableWebSecurity
public class SecurityConfigDb {
    
    @Bean
    public SecurityFilterChain mySecurityFilterChain(HttpSecurity http) throws Exception {

        http
                .cors(httpSecurityCorsConfigurer -> {
                    CorsConfiguration configuration = new CorsConfiguration();
                    configuration.setAllowedOrigins(Arrays.asList("*"));
                    configuration.setAllowedMethods(Arrays.asList("*"));
                    configuration.setAllowedHeaders(Arrays.asList("*"));
                    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
                    source.registerCorsConfiguration("/**", configuration);
                    httpSecurityCorsConfigurer.configurationSource(source);
                })
                // and etc
                ...

        return http.build();
    }
}
Kilmer answered 16/8, 2023 at 14:13 Comment(0)
T
3

as @Geoffrey pointed out, with spring security, you need a different approach as described here: Spring Boot Security CORS

Tribble answered 16/8, 2019 at 7:8 Comment(0)
R
3

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

Rundell answered 7/10, 2021 at 19:28 Comment(0)
F
1

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");
      }
    };
  }
}
Frisby answered 6/2, 2022 at 14:18 Comment(0)
M
0

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);
}
Misfeasor answered 9/10, 2018 at 11:17 Comment(0)
A
0

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("/**");
    }
}
Archiepiscopate answered 13/3, 2020 at 8:52 Comment(0)
O
0

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.

  1. 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);
      }
     }
    
  2. 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();
     }
    }
    
Osteal answered 9/6, 2021 at 16:54 Comment(0)
S
0

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("*");
        }
    }; 
  }
}
Swift answered 16/6, 2021 at 14:56 Comment(0)
N
0

I was facing same issue on Spring Boot 2.7.3 with Spring Security.

Fixed it by adding this Bean in my application. It worked without adding http.cors().and() code in Security Config class in my case.

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**").allowedOrigins("*").allowedMethods("*");
            }
        };
    }
Nahshunn answered 23/9, 2022 at 11:51 Comment(0)
T
-1
  • SpringBoot: 3.2.2
  • SpringSecurity: 6.2.1

The following solved the issue for me:

@Configuration
@EnableWebSecurity
public class SecurityFilterChainConfig {

    @Bean
    public SecurityFilterChain publicSecurityFilterChain(HttpSecurity http) throws Exception {

        http
                .cors(cors -> cors.configurationSource(corsConfigurationSource()))
                .securityMatchers(...)
                .csrf(AbstractHttpConfigurer::disable)
                .sessionManagement(manager -> manager
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                .authorizeHttpRequests(authorize -> 
                   // your configuration 
                   // and
                   .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                )
                ....;

        http.headers(header -> header.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Origin", "*")));
        
return http.build();
    }


public CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(allowedOrigins);
    configuration.setAllowedMethods(allowedMethods);
    configuration.setAllowCredentials(true);
    configuration.setAllowedHeaders(allowedHeaders);
    configuration.setExposedHeaders(exposedHeaders);

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);

    return source;
}

So the key was to add http.headers(header -> header.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Origin", "*"))); and .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()

Trustless answered 2/2 at 21:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.