java 在 Spring 5 Webflux 中启用 CORS?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46978794/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 09:26:54  来源:igfitidea点击:

Enable CORS in Spring 5 Webflux?

javaspringcorsspring-webflux

提问by Dachstein

How to enable CORSin a Spring 5 Webflux Project?

如何在 Spring 5 Webflux 项目中启用CORS

I cannot find any proper documentation.

我找不到任何适当的文件。

采纳答案by Dachstein

Here is another solution with the Webflux Configurer.

这是 Webflux 配置器的另一个解决方案。

Side Note: Its Kotlin Code (copied from my project) but you can easily translate that to Java Code.

旁注:它的 Kotlin 代码(从我的项目中复制)但您可以轻松地将其转换为 Java 代码。

@Configuration
@EnableWebFlux
class WebConfig: WebFluxConfigurer
{
    override fun addCorsMappings(registry: CorsRegistry)
    {
        registry.addMapping("/**")
            .allowedOrigins("*") // any host or put domain(s) here
            .allowedMethods("GET, POST") // put the http verbs you want allow
            .allowedHeaders("Authorization") // put the http headers you want allow
    }
}

回答by Zufar Muhamadeev

I had success with this custom filter:

我使用这个自定义过滤器取得了成功:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;

import reactor.core.publisher.Mono;


@Configuration
public class CorsConfiguration {

  private static final String ALLOWED_HEADERS = "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN";
  private static final String ALLOWED_METHODS = "GET, PUT, POST, DELETE, OPTIONS";
  private static final String ALLOWED_ORIGIN = "*";
  private static final String MAX_AGE = "3600";

  @Bean
  public WebFilter corsFilter() {
    return (ServerWebExchange ctx, WebFilterChain chain) -> {
      ServerHttpRequest request = ctx.getRequest();
      if (CorsUtils.isCorsRequest(request)) {
        ServerHttpResponse response = ctx.getResponse();
        HttpHeaders headers = response.getHeaders();
        headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
        headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
        headers.add("Access-Control-Max-Age", MAX_AGE);
        headers.add("Access-Control-Allow-Headers",ALLOWED_HEADERS);
        if (request.getMethod() == HttpMethod.OPTIONS) {
          response.setStatusCode(HttpStatus.OK);
          return Mono.empty();
        }
      }
      return chain.filter(ctx);
    };
  }

}

and org.springframework.boot:spring-boot-starter-webshould not be included as dependency - filter does not work with it.

并且org.springframework.boot:spring-boot-starter-web不应作为依赖项包含在内 - 过滤器不适用于它。

回答by milbr

@Configuration
public class WebFluxConfig {

    @Bean
    public WebFluxConfigurer corsConfigurer() {
        return new WebFluxConfigurerComposite() {

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

which corresponds to:

对应于:

@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurerAdapter() {

        @Override
        public void addCorsMappings(CorsRegistry registry) {

for spring mvc.

用于弹簧 mvc。

回答by Priyanshu Sekhar

Thanks to @Dachstein, replacing WebMvc configs with Webflux is the correct way of adding global CORS Config here.

感谢@Dachstein,用 Webflux 替换 WebMvc 配置是在此处添加全局 CORS 配置的正确方法。

@Configuration
@EnableWebFlux
public class CORSConfig implements WebFluxConfigurer {

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

回答by yuranos

If someone wants a Kotlin version of Zufar's answer(works like a charm with webflux routing functions) without additionally figuring out how Kotlin's SAM conversions work, here is the code:

如果有人想要 Zufar 答案的 Kotlin 版本(就像 webflux 路由功能的魅力一样),而不需要另外弄清楚 Kotlin 的 SAM 转换是如何工作的,这里是代码:

@Bean
fun corsFilter(): WebFilter {
    return WebFilter { ctx, chain ->
        val request = ctx.request
        if (CorsUtils.isCorsRequest(request)) {
            val response = ctx.response
            val headers = response.headers
            headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN)
            headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS)
            headers.add("Access-Control-Max-Age", MAX_AGE)
            headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS)
            if (request.method === HttpMethod.OPTIONS) {
                response.statusCode = HttpStatus.OK
                return@WebFilter Mono.empty<Void>()
            }
        }
        chain.filter(ctx)
    }
}

UPDATEAs I started testing it I found one problem with this solution. It's Ok if you really want to allow all methods. But imagine you want to only allow POSTand OPTIONS, for example. And the browser is trying to send PUT.

更新当我开始测试它时,我发现此解决方案存在一个问题。如果您真的想允许所有方法,那也没关系。但是假设您只想允许POSTOPTIONS,例如。并且浏览器正在尝试发送PUT.

Then a preflight response will basically say "hey, I can only serve POST and OPTIONS, but my HTTP status will be OKif you give me a request with Access-Control-Request-Method=PUT". It should be 403 Forbiddenhowever. What's more, most of those headers, like Access-Control-Allow-Methodsshould only be added to preflight requests, not all CORSrequests. Solution:

然后预检响应基本上会说“嘿,我只能提供 POST 和 OPTIONS,但OK如果你给我一个请求,我的 HTTP 状态将是Access-Control-Request-Method=PUT”。403 Forbidden然而它应该是。更重要的是,大多数这些标头,比如Access-Control-Allow-Methods应该只添加到预检请求,而不是所有CORS请求。解决方案:

@Bean
fun corsWebFilter(): CorsWebFilter {
    val corsConfig = CorsConfiguration()
    corsConfig.allowedOrigins = Arrays.asList(ALLOWED_ORIGINS)
    corsConfig.maxAge = MAX_AGE.toLong()
    //Notice it's singular. Can't be comma separated list
    corsConfig.addAllowedMethod(ALLOWED_METHOD)
    corsConfig.addAllowedHeader(ALLOWED_HEADER)

    val source = UrlBasedCorsConfigurationSource()
    source.registerCorsConfiguration(MATCH_ALL_PATH_SEGMENTS, corsConfig)

    return CorsWebFilter(source)
}

where

在哪里

const val MATCH_ALL_PATH_SEGMENTS = "/**"

回答by gtuz

Here is a link to the official documentation

这是官方文档的链接

https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-cors

https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-cors

There are 3 main options

有3个主要选项

1) Using the @CrossOrigin annotation on a rest controller - it can be used at class and/or method level

1) 在 rest 控制器上使用 @CrossOrigin 注释 - 它可以在类和/或方法级别使用

2) Implement the addCorsMapping method from the WebFluxConfigurer - it gives you an hook into the global CorsRegistry object

2) 从 WebFluxConfigurer 实现 addCorsMapping 方法 - 它为您提供了一个到全局 CorsRegistry 对象的钩子

3) Define a CorsWebFilter component - good choice for functional endpoints

3) 定义一个 CorsWebFilter 组件 - 功能端点的好选择

Please look at the docs, are well explained.

请看文档,有很好的解释。

Personally I use the third option when I want to allow cors while developing and I have decoupled the backend from the frontend module.

当我想在开发时允许使用 cors 并且我已经将后端与前端模块分离时,我个人使用第三个选项。

Imagine that you have webflux on a backend module while on the frontend you have a react or angular app. While developing the frontend features you might want to use webpack-dev-server for hot reloading while still running the backend on netty - the port will be different and this will cause CORS problem. With the third option you can easily link the @Component to @Profile("dev") so that when you deploy in prod CORS are enabled.

想象一下,您在后端模块上有 webflux,而在前端有一个 react 或 angular 应用程序。在开发前端功能时,您可能希望使用 webpack-dev-server 进行热重载,同时仍在 netty 上运行后端 - 端口将不同,这将导致 CORS 问题。使用第三个选项,您可以轻松地将 @Component 链接到 @Profile("dev") 以便在您在 prod 中部署时启用 CORS。