【问题标题】:Can you completely disable CORS support in Spring?您可以在 Spring 中完全禁用 CORS 支持吗?
【发布时间】:2017-11-25 15:26:51
【问题描述】:

CORS preflight request fails due to a standard header 中所述,如果您向OPTIONS 端点发送请求并设置了OriginAccess-Control-Request-Method 标头,那么它们会被Spring 框架拦截,并且您的方法不会被执行。公认的解决方案是使用@CrossOrigin 注释来阻止Spring 返回403。但是,我正在使用 Swagger Codegen 生成我的 API 代码,所以我只想禁用它并手动实现我的 OPTIONS 响应。

那么你可以在 Spring 中禁用 CORS 拦截吗?

【问题讨论】:

    标签: java spring spring-mvc swagger-codegen


    【解决方案1】:

    对于较新版本的 Spring Boot:

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

    Kotlin 方式

    @Configuration
    class WebConfiguration : WebMvcConfigurer {
        override fun addCorsMappings(registry: CorsRegistry) {
            registry.addMapping("/**").allowedMethods("*")
        }
    }
    

    【讨论】:

      【解决方案2】:

      来自他们的documentation

      如果你使用的是 Spring Web MVC

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

      如果您使用的是 Spring Boot:

      @Configuration
      public class MyConfiguration {
      
          @Bean
          public WebMvcConfigurer corsConfigurer() {
              return new WebMvcConfigurerAdapter() {
                  @Override
                  public void addCorsMappings(CorsRegistry registry) {
                      registry.addMapping("/**")
                              .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
                  }
              };
          }
      }
      

      Yuriy Yunikov 的回答也是正确的。但我不喜欢“自定义”过滤器。

      如果你有 Spring Web Security 给你带来麻烦。检查this SO 答案。

      【讨论】:

      • 此配置为所有来源和所有端点启用 CORS,发送“Access-Control-Allow-Origin: *”,这与禁用它相反。
      • 从 Spring 5.0 开始,WebMvcConfigurerAdapter 已被弃用,而改用 WebMvcConfigurer。
      【解决方案3】:

      尝试添加以下过滤器(您可以根据自己的需要和支持的方法自定义它):

      @Component
      public class CorsFilter extends OncePerRequestFilter {
      
          @Override
          protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
                                          final FilterChain filterChain) throws ServletException, IOException {
              response.addHeader("Access-Control-Allow-Origin", "*");
              response.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, PATCH, HEAD");
              response.addHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
              response.addHeader("Access-Control-Expose-Headers", "Access-Control-Allow-Origin, Access-Control-Allow-Credentials");
              response.addHeader("Access-Control-Allow-Credentials", "true");
              response.addIntHeader("Access-Control-Max-Age", 10);
              filterChain.doFilter(request, response);
          }
      }
      

      【讨论】:

      • 这篇文章被低估了!无论出于何种原因,我都无法让 CORS 在 spring-boot-starter-web 中工作......这篇文章解决了它!
      • 这里也一样,花了几个小时解决了这个问题!
      • 这里也一样,简洁明了。
      • 同意。我正在使用所有 spring 文档,正是这一点使它对我有用。
      【解决方案4】:

      我在我的 Spring Boot 应用程序中使用 Spring Security,并允许从特定域(或所有域)进行访问。

      我的WebSecurityConfig

      @Configuration
      @EnableWebSecurity
      public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
      
          // ...
      
          @Override
          protected void configure(HttpSecurity http) throws Exception {
      
              // add http.cors()
              http.cors().and().csrf().disable().authorizeRequests()
                      .antMatchers("/get/**").permitAll()
                      .antMatchers("/update/**").hasRole("ADMIN")
                      .anyRequest().authenticated()
                      .and()
                      .httpBasic(); // Authenticate users with HTTP basic authentication
      
              // REST is stateless
              http.sessionManagement()
                     .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
          }
      
          // To enable CORS
          @Bean
          public CorsConfigurationSource corsConfigurationSource() {
              final CorsConfiguration configuration = new CorsConfiguration();
      
              configuration.setAllowedOrigins(ImmutableList.of("https://www.yourdomain.com")); // www - obligatory
      //        configuration.setAllowedOrigins(ImmutableList.of("*"));  //set access from all domains
              configuration.setAllowedMethods(ImmutableList.of("GET", "POST", "PUT", "DELETE"));
              configuration.setAllowCredentials(true);
              configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
      
              final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
              source.registerCorsConfiguration("/**", configuration);
      
              return source;
          }
      
      }
      

      有时需要在测试前清除浏览器历史记录。

      详细信息可以在这里看到: http://appsdeveloperblog.com/crossorigin-restful-web-service/


      仅适用于使用 Angular 的用户。从 Angular 我向后端运行请求:

      export class HttpService {
      
        username = '..';
        password = '..';
        host = environment.api;
        uriUpdateTank = '/update/tank';
      
        headers: HttpHeaders = new HttpHeaders({
          'Content-Type': 'application/json',
          Authorization: 'Basic ' + btoa(this.username + ':' + this.password)
        });
      
        constructor(private http: HttpClient) {
        }
      
        onInsertTank(tank: Tank) {
          return this.http.put(this.host + this.uriUpdateTank, tank, {
            headers: this.headers
          })
            .pipe(
              catchError(this.handleError)
            );
        }
      ...
      }
      

      旧版本。 在我的 Spring Boot 应用程序中,没有其他方法可以工作:

      import org.springframework.core.Ordered;
      import org.springframework.core.annotation.Order;
      import org.springframework.stereotype.Component;
      
      import javax.servlet.*;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      
      @Component
      @Order(Ordered.HIGHEST_PRECEDENCE)
      public class RequestFilter implements Filter {
      
          public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
      
              HttpServletRequest request = (HttpServletRequest) req;
              HttpServletResponse response = (HttpServletResponse) res;
      
              response.setHeader("Access-control-Allow-Origin", "*");
              response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
              response.setHeader("Access-Control-Allow-Headers", "x-requested-with, x-auth-token");
              response.setHeader("Access-Control-Max-Age", "3600");
              response.setHeader("Access-Control-Allow-Credentials", "true");
      
              if (!(request.getMethod().equalsIgnoreCase("OPTIONS"))) {
                  try {
                      chain.doFilter(req, res);
                  } catch (Exception ex) {
                      ex.printStackTrace();
                  }
              } else {
                  System.out.println("Pre-flight");
                  response.setHeader("Access-Control-Allowed-Methods", "POST, GET, DELETE");
                  response.setHeader("Access-Control-Max-Age", "3600");
                  response.setHeader("Access-Control-Allow-Headers", "authorization, content-type,x-auth-token, " +
                          "access-control-request-headers, access-control-request-method, accept, origin, authorization, x-requested-with");
      
                  response.setStatus(HttpServletResponse.SC_OK);
              }
      
          }
      
          public void init(FilterConfig filterConfig) {
          }
      
          public void destroy() {
          }
      
      }
      

      【讨论】:

      • http.cors().and().csrf().disable() 这个工作就像魅力......干杯
      • 所有其他“现代”方法都失败了,但这种“旧版本”方法成功了!非常感谢!
      • @lukas84 为你高兴 :)
      • @KirillCh 老是金子。这是唯一对我有用的方法。谢谢!
      【解决方案5】:

      如果你至少有 Java 8,试试这个:

      @EnableWebSecurity
      public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
      
          @Override
          protected void configure(HttpSecurity http) throws Exception {
              http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());
          }
      }
      

      【讨论】:

        【解决方案6】:

        以前的答案几乎都是关于启用 CORS,这对我来说是禁用的。

        @Configuration
        public class MyConfig extends WebSecurityConfigurerAdapter {
        
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http.cors().and().csrf().disable();
            }
        
            @Bean
            public WebMvcConfigurer corsConfigurer() {
                return new WebMvcConfigurer() {
                    @Override
                    public void addCorsMappings(CorsRegistry registry) {
                        registry.addMapping("/**").allowedMethods("*");
                    }
                };
            }
        }
        

        【讨论】:

          【解决方案7】:

          Spring MVC

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

          春季启动

          @Configuration(proxyBeanMethods = false)
          public class MyConfiguration {
          
              @Bean
              public WebMvcConfigurer corsConfigurer() {
                  return new WebMvcConfigurer() {
                      @Override
                      public void addCorsMappings(final CorsRegistry registry) {
                          registry.addMapping("/**").allowedMethods("*").allowedHeaders("*");
                      }
                  };
              }
          }
          

          Spring 安全性(使用 Spring MVC 或 Spring Boot)

          @Configuration(proxyBeanMethods = false)
          public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
          
              @Override
              protected void configure(final HttpSecurity http) throws Exception {
                  // ...
          
                  // see also: https://docs.spring.io/spring-security/site/docs/5.5.3/reference/html5/#csrf-when
                  http.csrf().disabled();
          
                  // if Spring MVC is on classpath and no CorsConfigurationSource is provided,
                  // Spring Security will use CORS configuration provided to Spring MVC
                  http.cors(Customizer.withDefaults());
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2017-11-25
            • 1970-01-01
            • 2020-05-29
            • 2015-10-07
            • 2018-06-25
            • 1970-01-01
            • 1970-01-01
            • 2019-01-02
            • 2013-02-02
            相关资源
            最近更新 更多