Spring CORS 不存在“Access-Control-Allow-Origin”标头

Posted

技术标签:

【中文标题】Spring CORS 不存在“Access-Control-Allow-Origin”标头【英文标题】:Spring CORS No 'Access-Control-Allow-Origin' header is present 【发布时间】:2016-05-07 14:26:20 【问题描述】:

将 web.xml 移植到 java config 后出现以下问题

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access.

基于一些Spring引用,尝试了以下尝试:

@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);
    


选择的值取自一个有效的 web.xml 过滤器:

<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>

任何想法为什么 Spring java config 方法不像 web.xml 文件那样工作?

【问题讨论】:

【参考方案1】:

如果您想允许所有来源(*),请使用 setAllowedOriginPatterns 而不是 setAllowedOrigins

您可以点击以下链接

https://github.com/spring-projects/spring-framework/issues/26111

【讨论】:

【参考方案2】:

我通过使用 @CrossOrigin 注释在 Spring Boot 中找到了解决方案。

@Configuration
@CrossOrigin
public class WebConfig extends WebMvcConfigurerAdapter 

    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**");
    

【讨论】:

【参考方案3】:

我以这种方式解决了同样的问题。基本上添加这个@EnableWebSecurity注解并添加protected void configure(HttpSecurity http) throws Exception

从此改变:

@Configuration
public class WebConfig 

@Bean
public WebMvcConfigurer corsConfigurer() 
    return new WebMvcConfigurer() 
        @Override
        public void addCorsMappings(CorsRegistry registry) 
            registry.addMapping("/**").allowedMethods("*");
        
    ;

到这里

@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("*");
        
    ; 
  

【讨论】:

【参考方案4】:

经过大量的尝试和研究,这就是我解决 Access-Control-Allow-Origin 存在”问题的方法。

添加Spring security后,很多开发者面临cross origin问题,这就是解决这个问题的方法。

    添加自定义过滤器类的定义

    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);
      
     
    

    在配置类中添加自定义过滤器

    @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();
     
    
    

【讨论】:

【参考方案5】:

公共类 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");
            
        ;
    


【讨论】:

【参考方案6】:

由于某种原因,如果仍然有人无法绕过 CORS,请写下哪个浏览器想要访问您的请求的标头。

在你的配置文件中添加这个 bean。

@Bean
public WebSecurityConfigurerAdapter webSecurity() 
    return new WebSecurityConfigurerAdapter() 

        @Override
        protected void configure(HttpSecurity http) throws Exception 
            http.headers().addHeaderWriter(
                    new StaticHeadersWriter("Access-Control-Allow-Origin", "*"));


        
    ;

通过这种方式,我们可以告诉浏览器我们允许来自所有来源的跨域。如果您想限制特定路径,请将“*”更改为 'http://localhost:3000',""。

了解此行为的帮助参考https://www.concretepage.com/spring-4/spring-4-rest-cors-integration-using-crossorigin-annotation-xml-filter-example

【讨论】:

【参考方案7】:

正如@Geoffrey 指出的那样,使用弹簧安全性,您需要一种不同的方法,如下所述: Spring Boot Security CORS

【讨论】:

【参考方案8】:

我也收到了类似No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:63342' is therefore not allowed access.的消息

我已经正确配置了 cors,但是 RouterFuncion 中的 webflux 中缺少的是接受和内容类型标头 APPLICATION_JSON,就像这段代码中一样:

@Bean
RouterFunction<ServerResponse> routes() 
    return route(POST("/create")
                              .and(accept(APPLICATION_JSON))
                              .and(contentType(APPLICATION_JSON)), serverRequest -> create(serverRequest);

【讨论】:

【参考方案9】:

Omkar 的回答相当全面。

但全局配置部分的某些部分已更改。

根据spring boot 2.0.2.RELEASE reference

从 4.2 版开始,Spring MVC 支持 CORS。使用控制器方法 在 Spring Boot 中使用 @CrossOrigin 注释的 CORS 配置 应用程序不需要任何特定配置。全球 CORS 可以通过注册 WebMvcConfigurer bean 来定义配置 使用自定义的 addCorsMappings(CorsRegistry) 方法,如 下面的例子:

@Configuration
public class MyConfiguration 

    @Bean
    public WebMvcConfigurer corsConfigurer() 
        return new WebMvcConfigurer() 
            @Override
            public void addCorsMappings(CorsRegistry registry) 
                registry.addMapping("/api/**");
            
        ;
    

不过,这篇文章中的大多数答案都使用WebMvcConfigurerAdapter

The type WebMvcConfigurerAdapter is deprecated

从 Spring 5 开始你只需要实现接口 WebMvcConfigurer:

public class MvcConfig implements WebMvcConfigurer 

这是因为 Java 8 在接口上引入了默认方法 涵盖 WebMvcConfigurerAdapter 类的功能

【讨论】:

【参考方案10】:

根据 Omar 的回答,我在我的 REST API 项目中创建了一个名为 WebConfig.java 的新类文件,配置如下:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter 

  @Override
  public void addCorsMappings(CorsRegistry registry) 
    registry.addMapping("/**").allowedOrigins("*");
  
 

这允许任何源访问 API 并将其应用于 Spring 项目中的所有控制器。

【讨论】:

【参考方案11】:

有用的提示 - 如果您使用 Spring 数据休息,您需要一种不同的方法。

@Component
public class SpringDataRestCustomization extends RepositoryRestConfigurerAdapter 

 @Override
 public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) 
    config.getCorsRegistry().addMapping("/**")
            .allowedOrigins("http://localhost:9000");
  

【讨论】:

感谢这篇文章。当我注意到你的帖子说 Spring Data REST 使用不同的方法时,我有点失去希望了。现在完全适合我! RepositoryRestConfigurerAdapter 已弃用。直接实现RepositoryRestConfigurer即可。【参考方案12】:

我们遇到了同样的问题,我们使用 Spring 的 XML 配置解决了它,如下所示:

将此添加到您的上下文 xml 文件中

<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>

【讨论】:

【参考方案13】:

addCorsMappings 方法中将 CorsMapping 从 registry.addMapping("/*") 更改为 registry.addMapping("/**")

查看这个春季 CORS Documentation。

来自documentation -

为整个应用启用 CORS 非常简单:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter 

    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**");
    

您可以轻松更改任何属性,以及仅将此 CORS 配置应用于特定路径模式:

@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) 
    // ...
  

为整个控制器启用 CORS -

@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) 
        // ...
    

您甚至可以同时使用控制器级别和方法级别的 CORS 配置;然后 Spring 将结合两个注解的属性来创建合并的 CORS 配置。

@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) 
        // ...
    

【讨论】:

为整个应用程序启用 CORS 对我不起作用。 使用addCorsMapping 对我不起作用,我想说这是因为弹簧安全性...,但是按照here 的建议添加corsConfigurationSource bean 解决了我的问题。 也不要忘记允许所有客户端 registry.addMapping("/**").allowedOrigins("*"); spring.io/guides/gs/rest-service-cors 你是真正的救星。我正在使用 Spring 4.2 并尝试了无数其他替代方案,但在我尝试 addCorsMappings 覆盖方式之前,它们都无法正常工作。添加标准 CORS 标头以及 Access-Control-Allow-Headers 可能有帮助,也可能没有帮助 2020年了,spring boot注解还是不行。【参考方案14】:

如果您使用 Spring Security 版本 >= 4.2,则可以使用 Spring Security 的原生支持而不是包括 Apache:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter 

    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**");
    

上面的示例是从 Spring blog post 复制的,您还可以在其中找到有关如何在控制器上配置 CORS、特定控制器方法等的信息。此外,还有 XML 配置示例以及 Spring Boot 集成.

【讨论】:

以上是关于Spring CORS 不存在“Access-Control-Allow-Origin”标头的主要内容,如果未能解决你的问题,请参考以下文章

CORS 策略:请求的资源 Spring Boot Rest API 和 VUE 上不存在“Access-Control-Allow-Origin”标头

spring 控制器无法从 $http 角度检索数据

我们应该在发送响应时关闭飞行前 Cors 请求的连接吗?

Spring Data Rest 和 Cors

需要一种在 vueJS 中启用 CORS 的方法 [重复]

使用 Spring Framework 为 OPTIONS 请求启用 CORS