为Spring Cloud Gateway配置CORS策略



我让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并提交您的许可来源。

相关内容

  • 没有找到相关文章

最新更新