自学内容网 自学内容网

跨域资源共享 (CORS)

一、什么是跨域?

跨域是指浏览器发起的请求,其目标服务器与当前页面的来源(域名、协议、端口)不一致。例如:

  • 同源请求: 页面和接口来源一致,比如:
    • 页面地址:http://example.com
    • 请求接口:http://example.com/api
  • 跨域请求: 页面和接口来源不同,比如:
    • 页面地址:http://localhost:3000
    • 请求接口:http://localhost:8080/api

跨域问题的根源在于 浏览器的同源策略(Same-Origin Policy),这是一种安全机制,防止恶意站点通过 JavaScript 等方式访问用户敏感数据。

同源策略限制:浏览器的同源策略只允许当前网页(前端)的域名、端口、和协议与后端一致。如果前后端运行在不同的端口、协议或域名下(如前端在 http://localhost:3000,后端在 http://localhost:8080),这就是跨域,浏览器会阻止请求。

跨域的目的:

  • 如果跨域配置仅允许特定来源(如前端站点 http://localhost:3000)访问,那就是为了让你的前端能调用后端。
  • 如果配置允许所有来源(*),则是为了对任何来源的请求都开放,可能包括来自其他网站或恶意来源。

二、跨域问题的表现及解决方案

表现: 当浏览器发起跨域请求时,如果目标服务器没有正确配置跨域资源共享(CORS),会报类似以下错误:

Access to XMLHttpRequest at 'http://example.com/api' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

解决方案:
目标服务器通过 CORS 协议,明确告诉浏览器允许跨域请求。CORS 协议依赖以下 HTTP 头部字段:

  • Access-Control-Allow-Origin:允许的请求来源(如 http://localhost:3000*)。
  • Access-Control-Allow-Methods:允许的请求方法(如 GET, POST)。
  • Access-Control-Allow-Headers:允许的请求头(如 Content-Type, Authorization)。
  • Access-Control-Allow-Credentials:是否允许发送 Cookies 和凭据。

三、Spring Boot 中的跨域处理

Spring Boot 提供了多种方式来配置 CORS,根据项目需求灵活选择。

1. 局部跨域配置

使用 @CrossOrigin 注解,在控制器或具体方法上配置跨域规则,适合简单场景。

示例代码:

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @CrossOrigin(origins = "http://localhost:3000") // 允许来自 http://localhost:3000 的请求
    @GetMapping("/api/data")
    public String getData() {
        return "Hello, CORS!";
    }
}

优缺点:

  • 优点: 配置简单,针对单个接口有效。
  • 缺点: 对于多个接口的跨域需求不方便管理。

2. 全局跨域配置

方式 1:CorsRegistry

通过实现 WebMvcConfigurer 接口,配置全局跨域规则,适用于基于 Spring MVC 的项目。

示例代码:

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("http://localhost:3000") // 允许的请求来源
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的请求方法
                .allowedHeaders("*") // 允许的请求头
                .allowCredentials(true) // 允许携带 Cookies 或凭据
                .maxAge(3600); // OPTIONS 预检请求的缓存时间
    }
}
方式 2:CorsWebFilter

对于基于 Spring WebFlux 的响应式项目,需要使用 CorsWebFilter 处理跨域。

示例代码:

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;

@Configuration
public class CorsConfig {

    @Bean
    public CorsWebFilter corsWebFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("*"); // 允许所有来源
        config.addAllowedHeader("*"); // 允许所有请求头
        config.addAllowedMethod("*"); // 允许所有方法
        config.setAllowCredentials(true); // 允许凭据
        source.registerCorsConfiguration("/**", config);
        return new CorsWebFilter(source);
    }
}
两种方式的区别
  • CorsRegistry

    • 属于 Spring MVC,用于配置基于 Servlet 的传统 Web 应用。
    • 实现 WebMvcConfigurer 接口,通过 addCorsMappings 方法设置 CORS 规则。
    • 常用于传统的 Spring Boot Web 应用。
  • CorsWebFilter

    • 属于 Spring WebFlux,用于响应式(Reactive)编程模型的项目。
    • 基于过滤器机制实现,配置较灵活。
    • 适合需要处理响应式流的项目(如高并发或非阻塞请求)。

3. Spring Security 跨域处理

Spring Security 默认会拦截跨域请求,必须显式开启跨域支持。

代码示例:

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors() // 启用跨域支持
            .and()
            .csrf().disable(); // 禁用 CSRF,避免冲突
    }
}

注意:
Spring Security 只负责跨域支持的“开关”,具体跨域规则仍需通过 CorsRegistryCorsWebFilter 等方式配置。


4. 通过配置文件处理跨域

Spring Boot 提供了简化的方式,通过 application.propertiesapplication.yml 文件声明跨域规则,无需额外的配置类。

示例配置:

spring.web.cors.allowed-origins=http://localhost:3000
spring.web.cors.allowed-methods=GET,POST,PUT,DELETE
spring.web.cors.allowed-headers=*
spring.web.cors.allow-credentials=true
spring.web.cors.max-age=3600

优点:

  • 配置简单,无需编写代码。
  • 适用于跨域规则稳定的场景。

注意:
即使使用配置文件处理跨域,在 Spring Security 项目中仍需手动开启跨域支持(http.cors())。


四、Spring Cloud Gateway 的跨域处理

在微服务架构中,Spring Cloud Gateway 通常作为 API 网关,代理不同微服务的请求。跨域请求可以在网关层统一处理,避免每个微服务都重复配置跨域。

方式 1:使用 CorsWebFilter

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;

@Configuration
public class GatewayCorsConfig {

    @Bean
    public CorsWebFilter corsWebFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("*");
        config.addAllowedMethod("*");
        config.addAllowedHeader("*");
        config.setAllowCredentials(true);
        source.registerCorsConfiguration("/**", config);
        return new CorsWebFilter(source);
    }
}

方式 2:通过 application.yml 配置

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "http://localhost:3000"
            allowedMethods: "*"
            allowedHeaders: "*"
            allowCredentials: true

区别:

  • Spring Cloud Gateway 的 CorsWebFilter 作用于网关层,处理所有通过网关的跨域请求。
  • 普通 WebFlux 项目中的 CorsWebFilter 仅处理单个服务的跨域。

原文地址:https://blog.csdn.net/m0_73837751/article/details/143978415

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!