Java Spring Boot Webflux cors 被阻止

Posted

技术标签:

【中文标题】Java Spring Boot Webflux cors 被阻止【英文标题】:Java Spring Boot Webflux cors blocked 【发布时间】:2021-08-17 01:19:49 【问题描述】:

我正在尝试使用 Webflux 构建一个 Angular 和 Spring Boot 应用程序,而不是一开始就被包含实体和数据库的完整 CRUD 教程所困扰,我想我会先看看我是否可以得到客户端显示服务器返回的字符串,正如 Spring Boot 的文档所教导的那样 here。为此,我有以下代码:

//Angular client
  private currencyGreetingUrl: string;

  constructor(private http: HttpClient) 
    this.currencyGreetingUrl = 'http://localhost:8080/currency';
  

  public getCurrencyGreeting(): Observable<string> 
    return this.http.get<string>(this.currencyGreetingUrl);
  

//Spring Boot Web Client
@CrossOrigin(origins = "http://localhost:4200")
public class CurrencyWebClient 
  private WebClient client = WebClient.create("http://localhost:8080");

  private Mono<ClientResponse> result = client.get()
      .uri("/currency")
      .accept(MediaType.TEXT_PLAIN)
      .exchange();
  
  public String getResult() 
    return ">> result = " + result.flatMap(res -> res.bodyToMono(String.class)).block();
  


//Spring boot handler
@Component
public class CurrencyHandler 

  public Mono<ServerResponse> currency(ServerRequest request) 
    return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
      .body(BodyInserters.fromValue("Hello, Currency On The Go!"));
  


//Spring Boot router

@Configuration
public class CurrencyRouter 

  @Bean
  public RouterFunction<ServerResponse> route(CurrencyHandler currencyHandler) 

    return RouterFunctions
      .route(RequestPredicates.GET("/currency").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), currencyHandler::currency);
  


但是,在运行客户端和服务器Access to XMLHttpRequest at 'http://localhost:8080/currency' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.时出现此错误

我是 Spring Boot 新手,一直在四处寻找建议,但我通常会找到涉及配置、控制器类和其他比我目前拥有的更多构建工件的解决方案。我怎样才能让它工作?感谢您的帮助。

【问题讨论】:

Cors 是堆栈溢出中最常见的问题。 Spring 文档准确地告诉你如何解决这个问题,包括 100 多个在线教程和每周 50 个关于堆栈溢出的问题。 这是 java spring-boot 标签下被问得最多的问题。我已经阅读了您的问题,我对您的回答是 meta.***.com/questions/261592/… 注意 2 次投票。 CORS 上有大量文档developer.mozilla.org/en-US/docs/Web/HTTP/CORSdocs.spring.io/spring-framework/docs/current/reference/html/…spring.io/guides/gs/rest-service-corsspring.io/blog/2015/06/08/cors-support-in-spring-frameworkdocs.spring.io/spring-boot/docs/current/reference/htmlsingle/…en.wikipedia.org/wiki/Cross-origin_resource_sharingfetch.spec.whatwg.org/#http-cors-protocol 以后,使用 google 并找到您正在使用的框架的官方文档,并在询问堆栈溢出之前开始研究。这是您的答案docs.spring.io/spring-framework/docs/current/reference/html/…,它非常方便地位于官方 webflux 文档的 CORS 章节中。 【参考方案1】:

确实,我确实需要使用CorsWebFilter。然而,在阅读了一些关于 Spring Boot 及其依赖注入系统的内容,并查看了不使用功能端点的 Spring Boot 项目中不同的切线相关的 cors 实现后,我发现我必须将“CorsWebFilter”放在我的应用程序的根是这样的:

@SpringBootApplication
public class ServerApplication 
    public static void main(String[] args) 
        SpringApplication.run(ServerApplication.class, args);
        CurrencyWebClient client = new CurrencyWebClient();

        System.out.println(client.getResult());
    

    @Bean
    CorsWebFilter corsFilter() 

        CorsConfiguration config = new CorsConfiguration();

        config.setAllowCredentials(true);
        config.addAllowedOrigin("http://localhost:4200");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");

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

        return new CorsWebFilter(source);
    

当然,这不是唯一的方法。但它解决了我最初遇到的这个小问题。谢谢大家。

【讨论】:

【参考方案2】:

您已决定使用functional endpoints,并且您没有使用我从您的标签中可以看出的弹簧安全性,这意味着此处提供的所有其他答案都是错误的。

使用功能端点时,您必须知道您已选择不使用传统的基于注释的类。这意味着您失去了 spring 框架提供的许多免费功能

功能性端点更“低级”。因此,处理 CORS 的责任落在您开发人员身上。

如果你是 Spring 和 webflux 的初学者,我不会选择这条路线。

The documentation states in the CORS chapter in the official webflux documentation:

您可以通过内置的 CorsWebFilter 应用 CORS 支持, 非常适合功能端点

他们甚至提供了一个标准 CORS 过滤器的实现,您可以根据自己的需要进行自定义。

@Bean
CorsWebFilter corsFilter() 

    CorsConfiguration config = new CorsConfiguration();

    // Possibly...
    // config.applyPermitDefaultValues()

    config.setAllowCredentials(true);
    config.addAllowedOrigin("https://domain1.com");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");

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

    return new CorsWebFilter(source);

互联网上有 100 多个解释 CORS 的网页,这是 spring-boot、spring-security 标签中最常见的问题。我建议你阅读 CORS(在问这里之前你应该这样做)。

我强烈建议您从这里开始阅读:

Mozilla CORS

【讨论】:

很好,谢谢。事实是我想“进入 Spring Boot”,但是当我开始查找时,困难在于如何制作这样的应用程序有太多选择让我决定使用什么 - gradle v maven,wars v jars,我应该使用哪些依赖项,等等。 所以,我认为只需将tutorial 连接到我的客户端就足够简单了。并不是我没有尝试搜索如何启用 cors,您在我的问题中看到我向 WebClient 添加了注释。显然,我的错误是我没有考虑功能端点,它们的工作方式与我使用弹簧安全性不同。 该 bean 是否应该被注入到另一个类中?通读你得到 bean 的那篇 baeldung 文章,点击相关文章,搜索功能端点,但它没有回答这个问题。我用 bean 创建了一个低于应用程序根级别的文件,将允许的来源更改为http://localhost:4200,但仍然出现错误。尝试将允许的方法标头更改为Access-Control-Allow-Origin,并将允许的方法更改为GET,但仍然没有成功。 堆栈溢出不是论坛。这是一个问答网站。这个问题已经回答了。 Is the bean supposed to be injected into another class? Read through that baeldung article you got the bean from 我从不从 baeldung 网站获取信息,因为它们通常会提供错误的过时信息。如果您真的阅读了我的答案,您会发现我喜欢官方 webflux 文档,其中包含代码示例。如果你不明白答案,那么你应该从基础开始,也许从实现一个标准的 spring boot 应用程序开始,或者 google 上 bean 以及应该在哪里声明它们等等。【参考方案3】:

在需要快速测试的基于浏览器的前端使用 Webflux 时,我使用支持 CORS 的 Chrome 扩展来快速测试。这显然不适合生产。

如果您处于纯微服务/后端通信的情况,您可能只需要使用 Spring 的预期工作流程。以我的经验,Spring Webflux 有一些强大的结果,但设置很繁琐。您提到但正在避免的那些配置类,或者注解或基于 DSL 的 Kotlin 解决方案,不幸的是,目前是预期的方式。根据我的经验,它们确实有效,一旦你设置好它们,就可以为其他微服务制作一个快速的 github 就绪模板(我当时正在使用 Spring 和 Kotlin 构建微服务)。

编辑:我还要补充一点,你要避免的那些配置和类是值得你花时间的,即使你花一个上午的时间在这些上面也会为提高生产力铺平道路。 Webflux 很棒(我在 Kotlin 和 Java 中都使用过),但是当你跳转到异步/反应式 webflux 领域时,会有一些不可避免的陷阱和配置差异。当您意识到自己做对了事情时,配置中的乐趣就来了,当您可以推送这么多请求时,您的 DB 驱动程序会吓坏 :) :) :)

【讨论】:

感谢您的建议。探索这个的第一步很尴尬,这是在“好吧,我想要一个框架”和“好吧,让我们从小事做起”之间的考虑。【参考方案4】:

您是否正确配置了 cors? 如果没有尝试以下: https://***.com/a/67605427/9295125

由于发布的答案缺少一行,请同时阅读第二个答案。

【讨论】:

谢谢。试图遵循这一点,但由于我没有将安全性作为依赖项包括在内,因此存在问题。使用 gradle,将 compile "org.springframework.boot:spring-boot-starter-security" 添加到我的构建文件中,更新了类路径,但看起来它只是没有找到它。我可能会废弃并重新制作以安全性为依赖的项目,反正还没有做太多 用户没有指定使用spring security,从手头的问题来看,所以这不是一个答案,它链接到一个错误的答案。 对不起。原题中不包含使用的依赖或Pom

以上是关于Java Spring Boot Webflux cors 被阻止的主要内容,如果未能解决你的问题,请参考以下文章

finishConnect(..) 失败:连接被拒绝:localhost/127.0.0.1,错误:Webflux、Webclient、Spring boot、java

Spring Boot WebFlux 2.1.7 中文翻译文档

使用 Spring Boot WebFlux、Spring Data MongoDB Reactive 和 ReactiveMongoRepository 更新 1 个或多个特定字段 MongoDB

spring-boot-starter-web 和 spring-boot-starter-webflux 不能一起工作吗?

1 个 Spring Boot 应用程序中的 Spring mvc 和 webflux

服务器使用 Spring Boot 和 WebFlux 发送事件