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
Enable CORS in Spring 5 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-web
should 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 POST
and OPTIONS
, for example. And the browser is trying to send PUT
.
更新当我开始测试它时,我发现此解决方案存在一个问题。如果您真的想允许所有方法,那也没关系。但是假设您只想允许POST
和OPTIONS
,例如。并且浏览器正在尝试发送PUT
.
Then a preflight response will basically say "hey, I can only serve POST and OPTIONS, but my HTTP status will be OK
if you give me a request with Access-Control-Request-Method=PUT
". It should be 403 Forbidden
however.
What's more, most of those headers, like Access-Control-Allow-Methods
should only be added to preflight requests, not all CORS
requests.
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。