为 Spring Cloud Gateway 配置 CORS 策略

问题描述 投票:0回答:7

我在单独的服务器上运行 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
spring cors spring-cloud spring-cloud-gateway
7个回答
3
投票

您是否通过 --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

3
投票

我遇到了类似的问题,我做了以下事情:

我的 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 .


2
投票

你可以在你的安全类中添加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();
    }
}

2
投票

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 );
    }
}

1
投票

查看 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


0
投票

我想与您分享对我有用的解决方案,希望能帮助遇到同样问题的人:

@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
并提交您允许的来源。


0
投票

为了解决这个问题,我为我的 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',但只允许一个。”

© www.soinside.com 2019 - 2024. All rights reserved.