Java WebTestClient-带有Spring引导和Webflux的CORS
我有Vuejs前端和Spring Boot Webflux控制器。现在浏览器在调用Spring Boot时向CORS抱怨Java WebTestClient-带有Spring引导和Webflux的CORS,java,spring-boot,cors,spring-webflux,same-origin-policy,Java,Spring Boot,Cors,Spring Webflux,Same Origin Policy,我有Vuejs前端和Spring Boot Webflux控制器。现在浏览器在调用Spring Boot时向CORS抱怨 访问位于的XMLHttpRequest'https://...“起源”https://...'已被CORS策略阻止:对飞行前请求的响应未通过访问控制检查:请求的资源上不存在'access control Allow Origin'标头。 为了启用CORS,我尝试使用@CrossOrigin注释,如下所述: 但是它没有帮助,而且Spring在响应中没有发送CORS头,即使控制器
访问位于的XMLHttpRequest'https://...“起源”https://...'已被CORS策略阻止:对飞行前请求的响应未通过访问控制检查:请求的资源上不存在'access control Allow Origin'标头。
为了启用CORS,我尝试使用@CrossOrigin注释,如下所述:
但是它没有帮助,而且Spring在响应中没有发送CORS头,即使控制器中有@CrossOrigin注释
我还尝试了Bealdung教程中描述的WebTestClient,它确认了标题不存在:
java.lang.AssertionError: Response header 'Access-Control-Allow-Origin' expected:<[*]> but was:<null>
> OPTIONS /cors-enabled-endpoint
> WebTestClient-Request-Id: [1]
> Origin: [http://any-origin.com]
> Access-Control-Request-Method: [GET]
No content
< 500 INTERNAL_SERVER_ERROR Internal Server Error
< Vary: [Origin, Access-Control-Request-Method, Access-Control-Request-Headers]
0 bytes of content (unknown content-type).
你知道为什么上面链接中描述的CORS配置不起作用吗?我还尝试在全局配置上启用CORS,并使用WebFilter启用CORS。但似乎什么都不起作用。在@CrossOrigin
的
SpringWebMVC和SpringWebFlux都通过
RequestMappingHandlerMapping在各自的模块中。这个
添加来自每个类型和方法级别的注释对的值
到一个公司的配置
这意味着您的CORS设置将添加到
如果您使用的是Spring安全性,则需要这样做,以便使用您的CorsConfiguration。下面是一个小例子
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
...
}
从
添加要使用的CorsFilter。如果名为corsFilter的bean
前提是使用了过滤网。否则,如果CorsConfiguration源为
定义,然后使用该公司配置。否则,如果Spring MVC
在类路径上使用HandlerMappingIntrospector
注意,如果您正在发送带有请求(cookies)的凭据,则需要将其添加到CORS设置中
@CrossOrigin(allowCredentials = "true")
解决方案是对WebTestClient使用以下配置:
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
class MyTestClass {
@Autowired
private WebTestClient webTestClient;
@Test
void corsTest() {
ResponseSpec response = webTestClient.get()
.uri("/cors-enabled-endpoint")
.header("Origin", "http://any-origin.com")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Origin", "*");
}
}
我还需要添加springbootstarterweb
依赖项,这很奇怪,因为我只使用Webflux。但如果没有它,测试仍然会失败,出现IllegalArgumentException:实际请求方案不能为null
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
org.springframework.boot
SpringBootStarterWeb
现在,测试是绿色的 对于我来说,在不添加spring starter web依赖项的情况下,实际有效的方法是使用web筛选器,并在http方法为选项时强制返回
@Configuration
public class CorsGlobalConfiguration implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange,
WebFilterChain webFilterChain) {
ServerHttpRequest request = serverWebExchange.getRequest();
ServerHttpResponse response = serverWebExchange.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "POST, GET, PUT, OPTIONS, DELETE, PATCH");
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*");
headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");
headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "18000L");
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();//HERE
}
return webFilterChain.filter(serverWebExchange);
}
}
@配置
公共类CorsGlobalConfiguration实现WebFilter{
@凌驾
公共Mono筛选器(ServerWebExchange ServerWebExchange,
网络过滤器链(网络过滤器链){
ServerHttpRequest请求=serverWebExchange.getRequest();
ServerHttpResponse response=serverWebExchange.getResponse();
HttpHeaders=response.getHeaders();
headers.add(HttpHeaders.ACCESS\u CONTROL\u ALLOW\u ORIGIN,“*”);
添加(HttpHeaders.ACCESS\u CONTROL\u ALLOW\u方法,“POST、GET、PUT、OPTIONS、DELETE、PATCH”);
添加(HttpHeaders.ACCESS\u CONTROL\u ALLOW\u凭证,“true”);
headers.add(HttpHeaders.ACCESS\u CONTROL\u ALLOW\u headers,“*”);
添加(HttpHeaders.ACCESS\u CONTROL\u EXPOSE\u headers,“*”);
headers.add(HttpHeaders.ACCESS\u CONTROL\u MAX\u AGE,“18000L”);
if(request.getMethod()==HttpMethod.OPTIONS){
response.setStatusCode(HttpStatus.OK);
返回Mono.empty();//此处
}
返回webFilterChain.filter(serverWebExchange);
}
}
@RichArt的解决方案是99%接近-但您不需要依赖性(spring boot starter web);因为它正在检查CORS,所以Spring似乎需要帮助了解您在测试中使用的方案和主机;它无法派生“scheme”(http)或URI较短的主机
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
class MyTestClass {
@Autowired
private WebTestClient webTestClient;
@LocalServerPort
private Int lsp;
@Test
void corsTest() {
ResponseSpec response = webTestClient.get()
.uri("http://localhost" + lsp.toString() + "/cors-enabled-endpoint")
.header("Origin", "http://any-origin.com")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Origin", "*");
}
}
非常感谢你的回答。在仔细阅读了它,并且再次阅读了文档之后,我仍然有同样的问题。实际上,我不使用Spring安全性。还有一件事:运行测试也会出现此错误:
2020-07-04 13:44:45.611错误17867---[parallel-1]o.s.w.s.adapter.httpwebhandleradopter:[38a66881]500 HTTP GET的服务器错误“/cors启用的端点”
java.lang.IllegalArgumentException:实际请求方案不能为null
这可能是根本原因,但我在internet上找不到帮助资源。您能帮忙吗?@RichArt请确保您将CrossOrigin放在发送请求的同一请求映射上。如果将CrossOrigin放在GET“/api/users”上,则CORS将仅对GET“/api/users”启用。您还可以将CrossOrigin置于控制器级别,然后CORS将可用于控制器中的所有请求映射,例如POST“/api/users”GET“/api/users”等。当然,这将取决于您在控制器中的CORS配置中允许的方法。
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
class MyTestClass {
@Autowired
private WebTestClient webTestClient;
@LocalServerPort
private Int lsp;
@Test
void corsTest() {
ResponseSpec response = webTestClient.get()
.uri("http://localhost" + lsp.toString() + "/cors-enabled-endpoint")
.header("Origin", "http://any-origin.com")
.exchange();
response.expectHeader()
.valueEquals("Access-Control-Allow-Origin", "*");
}
}