我在单独的服务器上运行 Spring Cloud 网关,配置如下:
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/*]': (I also tried '[/**]':)
allowedOrigins: "http://localhost:3000"
allowedMethods:
- GET
- POST
但是每次从 React 应用程序我得到:
从来源“http://localhost:3000”访问位于“http://11.1.1.1:8080/api/support/tickets/create”的 XMLHttpRequest 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。
你知道 Spring Boot 2.6.2/Spring cloud 2021.0.0 如何解决这个问题吗?
完整代码:http://www.github.com/rcbandit111/Spring_Cloud_Gateway_POC
POST请求:
Request URL: http://1.1.1.1:8080/api/merchants/onboarding/bank_details
Referrer Policy: strict-origin-when-cross-origin
Accept: application/json, text/plain, */*
Content-Type: application/json
Referer: http://localhost:3000/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
Post request Payload:
{"currency":"HNL","iban":"dssvsdvsdv"}
OPTIONS请求:
Request URL: http://1.1.1.1:8080/api/merchants/onboarding/bank_details
Request Method: OPTIONS
Status Code: 403 Forbidden
Remote Address: 1.1.1.1:8080
Referrer Policy: strict-origin-when-cross-origin
回复:
HTTP/1.1 403 Forbidden
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
content-length: 0
OPTIONS请求标头:
OPTIONS /api/merchants/onboarding/bank_details HTTP/1.1
Host: 1.1.1.1:8080
Connection: keep-alive
Accept: */*
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
Sec-Fetch-Mode: cors
Referer: http://localhost:3000/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
您是否通过 --proxy-conf 运行您的 FE 应用程序以进行重定向?我不太精通 FE,但不要使用 changeOrigin: true。如果您必须使用 changeOrigin: true,它仅适用于 GET,而对于其他人,您可能必须执行类似 this 的操作。 要使用 proxy-conf,我们通常有一个
proxy.conf.json
这样的东西:
{
"/api/*": {
"target": "http://external-gateway-url",
"secure": false,
"logLevel": "debug"
}
}
然后在运行应用程序时使用
--proxy-config proxy.conf.json
。我的有限元知识已经过时了。你可能想要看起来像this.
如果不是,并且调用是直接的,那么网关中的以下配置(代理也需要)应该可以工作:
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "http://localhost:3000"
allowedHeaders: "*"
allowedMethods:
- GET
- POST
我遇到了类似的问题,我做了以下事情:
我的 application.yml 包含将 CORS 配置添加到每个路由:
spring:
cloud:
gateway:
globalcors:
add-to-simple-url-handler-mapping: true
然后我配置了一个spring标准的CorsWebFilter Bean。请注意,对于生产,您不应将 * 用于 AllowedOrigins 属性。对于开发目的,这非常好。
@Configuration
public class CorsConfiguration extends org.springframework.web.cors.CorsConfiguration {
@Bean
public CorsWebFilter corsFilter() {
org.springframework.web.cors.CorsConfiguration corsConfiguration = new org.springframework.web.cors.CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD"));
corsConfiguration.addAllowedHeader("origin");
corsConfiguration.addAllowedHeader("content-type");
corsConfiguration.addAllowedHeader("accept");
corsConfiguration.addAllowedHeader("authorization");
corsConfiguration.addAllowedHeader("cookie");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfiguration);
return new CorsWebFilter(source);
}
}
注意:我有版本 2.3.9.Release for spring boot 和 spring cloud 版本是 Hoxton.SR10 .
你可以在你的安全类中添加cors配置。像这样
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
private SecurityRepository securityRepository;
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http){
http
.cors().configurationSource(request -> {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of("http://localhost:3000"));
configuration.setAllowedMethods(List.of("*"));
configuration.setAllowedHeaders(List.of("*"));
return configuration;
});
http.csrf().disable();
return http.build();
}
}
Tr1monster 的答案有效并且可能是最好的方法。
Java配置的稍微更紧凑的版本:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import java.util.List;
@Configuration
public class CorsConfig
extends CorsConfiguration
{
@Bean
public CorsWebFilter corsFilter()
{
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials( true );
config.setAllowedOrigins( List.of( "*" ) );
config.setAllowedMethods( List.of( "GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD" ) );
config.setAllowedHeaders( List.of( "origin", "content-type", "accept", "authorization", "cookie" ) );
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration( "/**", config );
return new CorsWebFilter( source );
}
}
查看 MDN Web 文档中关于 CORS 的部分Simple requests:
标头中指定的媒体类型允许的唯一类型/子类型组合是:Content-Type
application/x-www-form-urlencoded
multipart/form-data
text/plain
因为您使用值
application/json
作为请求的 Content-Type
标头,所以您需要在 CORS 配置中允许该标头:
cors-configurations:
'[/**]':
allowedOrigins: "http://localhost:3000"
allowedMethods:
- GET
- POST
allowedHeaders:
- Content-Type
我想与您分享对我有用的解决方案,希望能帮助遇到同样问题的人:
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
@Autowired
private ReactiveClientRegistrationRepository clientRegistrationRepository;
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
CorsConfiguration cors_config = new CorsConfiguration();
cors_config.setAllowCredentials(true);
cors_config.applyPermitDefaultValues();
cors_config.setAllowedOrigins(Arrays.asList("http://localhost:3000", "null"));
cors_config.setAllowedMethods(List.of("GET","POST","OPTIONS","DELETE"));
cors_config.setAllowedHeaders(List.of("*"));
http.cors().configurationSource(source -> cors_config)
.and()
.csrf().disable()
.authorizeExchange(exchanges -> exchanges.anyExchange().authenticated())
.oauth2Login()//Setting Oauth2Login
.authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("<MyLogoutURL>")).and()
.logout(logout -> logout //Setting Oauth2Logout
.logoutHandler(logoutHandler())
.logoutSuccessHandler(oidcLogoutSuccessHandler()));
return http.build();
}
private ServerLogoutSuccessHandler oidcLogoutSuccessHandler() {
OidcClientInitiatedServerLogoutSuccessHandler oidcLogoutSuccessHandler =
new OidcClientInitiatedServerLogoutSuccessHandler(this.clientRegistrationRepository);
// Sets the location that the End-User's User Agent will be redirected to
// after the logout has been performed at the Provider
oidcLogoutSuccessHandler.setPostLogoutRedirectUri("http://google.com");
return oidcLogoutSuccessHandler;
}
private DelegatingServerLogoutHandler logoutHandler() {
//Invalidate session on logout
return new DelegatingServerLogoutHandler(
new SecurityContextServerLogoutHandler(), new WebSessionServerLogoutHandler());
}
}
确保在 Keycloak 上也启用了 cors,导航到
realm->clients->settings->weborigins
并提交您允许的来源。
为了解决这个问题,我为我的 Spring Cloud Gateway 设置了以下配置
spring:
cloud:
gateway:
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "http://127.0.0.1:3000,http://127.0.0.1:3001"
allowedHeaders: "*"
allowedMethods:
- GET
- POST
- DELETE
- PUT
- OPTIONS
我从这次讨论中得出了这个解决方案:https://github.com/spring-cloud/spring-cloud-gateway/issues/840
请注意,您需要添加 default-filters 配置以修复以下问题:
":已被 CORS 策略阻止:'Access-Control-Allow-Origin' 标头包含多个值 'http://127.0.0.1:3000, http://127.0.0.1:3000',但只允许一个。”