【开发篇】明明设置允许跨域,为什么还会出现跨域请求的问题

一、问题

在微服务项目中,明明已经设置允许跨域访问:

为什么还会出现跨域请求问题?

二、为什么

仔细查看错误提示信息:When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.

原来当我们设置allowCredentials 参数为 true时,allowedOrigins参数将不再允许被设置为“*”参数,可以使用"allowedOriginPatterns"来替代。

那么为什么CORS要有这样的规定?allowCredentials参数又是什么鬼?

Allow-Credentials 参数在跨域资源共享(CORS)策略中用于指定是否允许浏览器发送包含凭证的请求。凭证包括 cookies、HTTP 认证信息等。当 Allow-Credentials 设置为 true 时,浏览器将允许前端应用程序在跨域请求中发送这些凭证。

在 HTTP 响应头中,Access-Control-Allow-Credentials 用于告知浏览器服务端是否允许跨域请求携带凭证。

可以看到,当我们设置Allow-Credentials 参数为true时,将会携带cookies、HTTP认证等这些比较敏感的安全信息的,因此 CORS 规范要求,当 allowCredentials 设置为 true 时,不能使用通配符 * 来表示允许所有来源(origin),而必须要明确指定允许的来源

三、怎么办

单就解决这个问题来说,我们可以有以下两个方案:

方案一:明确列出允许的来源:你可以列出具体的域名,而不是使用通配符 *。

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("https://example.com", "https://anotherdomain.com")
                .allowedHeaders("*")
                .allowedMethods("*")
                .allowCredentials(true);
    }

}

方案二:使用 allowedOriginPatterns:从 Spring Framework 5.3 开始,支持使用 allowedOriginPatterns,它可以使用通配符并且与 allowCredentials 一起使用。

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*") // 使用 allowedOriginPatterns 而不是 allowedOrigins
                .allowedHeaders("*")
                .allowedMethods("*")
                .allowCredentials(true);
    }

}

四、总结

那么在Spring Boot微项目中什么情况下要设置 allowCredentials(true) 呢?

可以参考以下几个方面考虑:

1、是否需要跨域请求携带凭据:

如果你的前端应用需要通过跨域请求来访问另一个域名下的微服务,并且这些请求需要携带凭据(如 cookies、HTTP 认证信息或者客户端证书),那么你需要设置 allowCredentials(true)。
例如,如果你的前端应用和后端 API 部署在不同的域名上,并且你使用了基于 Session 或 Cookie 的身份验证机制,那么 allowCredentials(true) 是必须的。

2、安全性考虑:

在允许跨域请求携带凭据的情况下,确保你只允许受信任的来源。明确列出受信任的域名比使用 * 通配符更安全。
使用 allowedOriginPatterns 可以配合 allowCredentials(true),但也应小心配置,避免开放过多不受控的来源。

3、API 的设计方式:

如果你的微服务是无状态的,并且主要依赖于 token(如 JWT)来进行认证和授权,那么通常不需要依赖 cookies 或其他凭据机制,这种情况下可以避免使用 allowCredentials(true)。

五、推荐

        在Spring Cloud微服务项目中,前端调用一个后端API接口的请求路径通常是这样的:前端 >> 网关 >> 后端服务,即:

  • 统一由网关接收前端请求并转发后端服务
  • API通常采用token(JWT)进行认证授权

所以关于CORS跨域请求咱们可以这么处理:

1、Spring Boot后端服务

        Spring Boot后端服务不需要接收Cookie等信息,因此不用设置allowCredentials参数。

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedHeaders("*")
                .allowedMethods("*");
    }

}

2、Spring Cloud Gateway网关

        网关通常需要拦截接收处理前端请求的cookie等信息,因此可以设置allowCredentials参数为true。可以在Spring Cloud Gateway的application.yml中进行如下配置:

spring:
  cloud:
    gateway:
      # 跨域属性配置
      globalcors:
        cors-configurations:
          '[/**]':
            max-age: 3600
            allowed-origin-patterns: "https://*.example.com"
            allowed-headers: "*"
            allow-credentials: true
            allowed-methods:
              - GET
              - POST
              - DELETE
              - PUT
              - OPTION

六、提外话

        在SpringBoot中关于跨域处理的写法,在SpringFramework5.0之前通常是以继承WebMvcConfigurerAdapter方式实现的,Spring5.0之后,WebMvcConfigurerAdapter这个类已被标记为@Deprecated,不再建议使用了。

@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {

    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        return corsConfiguration;
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsFilter(source);
    }

}

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gary强z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值