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可能更合适。