CORS issue - No 'Access-Control-Allow-Origin' header is present on the requested resource

前端 未结 5 1696
旧巷少年郎
旧巷少年郎 2020-11-22 13:20

I have created two web applications - client and service apps.
The interaction between client and service apps goes fine when they are deployed in same Tomcat instance.

相关标签:
5条回答
  • 2020-11-22 13:47

    Since Spring Security 4.1, this is the proper way to make Spring Security support CORS (also needed in Spring Boot 1.4/1.5):

    @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
        }
    }
    

    and:

    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
    //        http.csrf().disable();
            http.cors();
        }
    
        @Bean
        public CorsConfigurationSource corsConfigurationSource() {
            final CorsConfiguration configuration = new CorsConfiguration();
            configuration.setAllowedOrigins(ImmutableList.of("*"));
            configuration.setAllowedMethods(ImmutableList.of("HEAD",
                    "GET", "POST", "PUT", "DELETE", "PATCH"));
            // setAllowCredentials(true) is important, otherwise:
            // The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
            configuration.setAllowCredentials(true);
            // setAllowedHeaders is important! Without it, OPTIONS preflight request
            // will fail with 403 Invalid CORS request
            configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
            final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", configuration);
            return source;
        }
    }
    

    Do not do any of below, which are the wrong way to attempt solving the problem:

    • http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
    • web.ignoring().antMatchers(HttpMethod.OPTIONS);

    Reference: http://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/cors.html

    0 讨论(0)
  • 2020-11-22 13:48

    Add the below configuration in main application. It worked me in spring boot application 2.3.1

    package com.example.restservicecors;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.servlet.config.annotation.CorsRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @SpringBootApplication
    public class RestServiceCorsApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(RestServiceCorsApplication.class, args);
        }
    
        @Bean
        public WebMvcConfigurer corsConfigurer() {
            return new WebMvcConfigurer() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("*");
                }
            };
        }
    
    }
    

    Reference source: https://spring.io/guides/gs/rest-service-cors/

    0 讨论(0)
  • 2020-11-22 13:54

    CORS' preflight request uses HTTP OPTIONS without credentials, see Cross-Origin Resource Sharing:

    Otherwise, make a preflight request. Fetch the request URL from origin source origin using referrer source as override referrer source with the manual redirect flag and the block cookies flag set, using the method OPTIONS, and with the following additional constraints:

    • Include an Access-Control-Request-Method header with as header field value the request method (even when that is a simple method).
    • If author request headers is not empty include an Access-Control-Request-Headers header with as header field value a comma-separated list of the header field names from author request headers in lexicographical order, each converted to ASCII lowercase (even when one or more are a simple header).
    • Exclude the author request headers.
    • Exclude user credentials.
    • Exclude the request entity body.

    You have to allow anonymous access for HTTP OPTIONS.

    Your modified (and simplified) code:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
       http
           .authorizeRequests()
               .andMatchers(HttpMethod.OPTIONS, "/**").permitAll()
               .antMatchers("/login").permitAll()
               .anyRequest().fullyAuthenticated()
               .and()
           .httpBasic()
               .and()
           .sessionManagement()
               .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
               .and()
           .csrf().disable();
    }
    

    Since Spring Security 4.2.0 you can use the built-in support, see Spring Security Reference:

    19. CORS

    Spring Framework provides first class support for CORS. CORS must be processed before Spring Security because the pre-flight request will not contain any cookies (i.e. the JSESSIONID). If the request does not contain any cookies and Spring Security is first, the request will determine the user is not authenticated (since there are no cookies in the request) and reject it.

    The easiest way to ensure that CORS is handled first is to use the CorsFilter. Users can integrate the CorsFilter with Spring Security by providing a CorsConfigurationSource using the following:

    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          http
              // by default uses a Bean by the name of corsConfigurationSource
              .cors().and()
              ...
      }
    
      @Bean
      CorsConfigurationSource corsConfigurationSource() {
          CorsConfiguration configuration = new CorsConfiguration();
          configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
          configuration.setAllowedMethods(Arrays.asList("GET","POST"));
          UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
          source.registerCorsConfiguration("/**", configuration);
          return source;
      }
    }
    
    0 讨论(0)
  • 2020-11-22 14:00

    In my case, I have Resource Server with OAuth security enabled and any of above solutions didn't work. After some debugging and googling figured why.

    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    }
    

    Basically in this example Ordered.HIGHEST_PRECEDENCE is key!

    https://github.com/spring-projects/spring-security-oauth/issues/938

    Various pom dependencies add different kinds of filters and therefore we could have issues based on order.

    0 讨论(0)
  • 2020-11-22 14:13

    This worked for: spring-boot-starter-parent 2.2.6.RELEASE

    @Configuration
    @EnableWebMvc
    public class WebConfig implements WebMvcConfigurer {
    
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("*");
        }
    }
    

    Change "*" to something meaningful in prod

    0 讨论(0)
提交回复
热议问题