我让Spring Cloud网关在单独的服务器上运行,配置如下:
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/*]': (I also tried '[/**]':)
allowedOrigins: "http://localhost:3000"
allowedMethods:
- GET
- POST
但每次从React应用程序我都会得到:
访问'XMLHttpRequesthttp://11.1.1.1:8080/api/support/tickets/create'来自原点'http://localhost:3000'已被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,而对于其他人,你可能必须这样做。要使用proxy-conf,我们通常有一个proxy.conf.json
,其中包含以下内容:
{
"/api/*": {
"target": "http://external-gateway-url",
"secure": false,
"logLevel": "debug"
}
}
然后在运行应用程序时使用CCD_ 2。我的FE知识已经过时了。你可能想看起来像这样。
如果不是,并且调用是直接的,那么网关中的以下配置(代理也需要(应该可以工作:
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标准的CorsWebFilterBean。请注意,对于生产,不应将*用于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版本。发布版本为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:的标题为简单请求的部分
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
为了解决这个问题,我为我的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
请注意,您需要添加默认的过滤器配置来修复以下问题:
":已被CORS策略阻止:"Access Control Allow Origin"标头包含多个值'http://127.0.0.1:3000,http://127.0.0.1:3000',但只允许使用一个">
我想与您分享一个对我有用的解决方案,希望能帮助任何面临同样问题的人:
@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());
}
}
确保在Keycloft上也启用了cors,导航到realm->clients->settings->weborigins
并提交您的许可来源。