Spring Boot 跨域问题

出错问题: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.

CORS(Cross-Origin Resource Sharing,跨源资源共享是一种安全机制,用于控制一个域下的 Web 应用如何能够向另一个域的服务器发起请求。这是浏览器出于安全考虑而实施的一种限制,称为同源策略(Same-Origin Policy)。同源策略要求一个网页只能请求与其相同源(协议、域名和端口号)的资源。

CORS 问题的常见场景:

  1. Web 应用请求其他域的 API:当你的 Web 应用尝试从不同的源(例如,从 https://example.com 请求 https://api.otherdomain.com/data)获取数据时,浏览器会阻止这些请求,除非后者服务器明确允许。
  2. 前端和后端分离部署:在现代 Web 开发中,前端页面和后端服务可能部署在不同的服务器或域上。如果没有适当配置 CORS,前端页面将无法从后端服务获取数据。
  3. 第三方服务集成:当你的网站需要集成第三方服务(如社交媒体登录、地图服务等),这些服务的 API 可能位于不同的域。

CORS 问题的解决方法:

  1. 服务器端配置:服务器需要在其响应中包含适当的 CORS 头(如 Access-Control-Allow-Origin),以指示哪些客户端源可以访问资源。
  2. 使用代理:在某些情况下,可以通过设置一个代理服务器来绕过 CORS 限制。代理服务器接收前端的请求,然后转发到目标服务器,并将响应返回给前端。
  3. 浏览器插件:虽然不推荐在生产环境中使用,但开发过程中可以使用浏览器插件临时禁用同源策略。
  4. 文档域:通过设置 document.domain,可以使得两个具有相同主域但不同子域的页面共享文档对象。
  5. JSONP(已过时):JSONP(JSON with Padding)是一种早期的解决方案,通过动态创建 <script> 标签来绕过同源策略限制,但由于安全性问题,现在不推荐使用。

CORS 配置方案

一、注解配置

服务器端(例如使用 Spring Boot):

// 允许所有域访问
@CrossOrigin(origins = "*")
@GetMapping("/api/data")
public ResponseEntity<?> getData() {
// ...
}

或者更精细的控制:

// 允许特定域访问
@CrossOrigin(origins = "https://example.com")
@GetMapping("/api/data")
public ResponseEntity<?> getData() {
// ...
}

正确配置 CORS 对于确保 Web 应用的安全性和功能性至关重要。

在 Spring Boot 应用中,处理跨域资源共享(CORS)问题可以通过两种主要方式:使用 CorsFilter 和使用 addCorsMappings 方法。这两种方法各有特点和适用场景:

二、使用 CorsFilter

CorsFilter 是一个 Spring 框架提供的过滤器,用于处理 CORS 相关的配置。你可以自定义这个过滤器来设置更复杂的 CORS 策略。

优点

  • 灵活性高:可以非常灵活地配置 CORS 策略,包括对不同的 URL 路径应用不同的 CORS 规则。
  • 细粒度控制:可以精确控制哪些请求方法、请求头和来源被允许。

缺点

  • 配置复杂:相比于 addCorsMappings,配置可能更复杂一些。
  • 性能考虑:作为一个过滤器,可能会有轻微的性能开销。

示例代码

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {

@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}

三、使用 addCorsMappings 方法

addCorsMappings 方法是 WebMvcConfigurer 接口的一部分,允许你直接在配置类中定义 CORS 映射。这种方法更简洁,适合大多数基本的 CORS 需求。

优点

  • 简单易用:代码更简洁,易于理解和维护。
  • 无需创建额外的 Bean:直接在配置类中定义,不需要额外定义 Bean。

缺点

  • 灵活性较低:相比于 CorsFilteraddCorsMappings 提供的配置选项较少,不够灵活。

示例代码

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
}

选择哪种方式?

  • 如果需要简单的 CORS 配置,推荐使用 addCorsMappings 方法,因为它简单且易于实现。
  • 如果需要更复杂的 CORS 策略,例如对不同的 URL 应用不同的 CORS 规则,或者需要动态决定 CORS 策略,那么使用 CorsFilter 可能更合适。