跨域是指浏览器发起的请求,其目标服务器与当前页面的来源(域名、协议、端口)不一致。例如:
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 提供了多种方式来配置 CORS,根据项目需求灵活选择。
使用 @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!";
}
}
优缺点:
通过实现 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 预检请求的缓存时间
}
}
对于基于 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:
WebMvcConfigurer
接口,通过 addCorsMappings
方法设置 CORS 规则。CorsWebFilter:
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 只负责跨域支持的“开关”,具体跨域规则仍需通过 CorsRegistry
或 CorsWebFilter
等方式配置。
Spring Boot 提供了简化的方式,通过 application.properties
或 application.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 通常作为 API 网关,代理不同微服务的请求。跨域请求可以在网关层统一处理,避免每个微服务都重复配置跨域。
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);
}
}
application.yml
配置spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "http://localhost:3000"
allowedMethods: "*"
allowedHeaders: "*"
allowCredentials: true
区别:
CorsWebFilter
作用于网关层,处理所有通过网关的跨域请求。CorsWebFilter
仅处理单个服务的跨域。因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo2.com 版权所有 湘ICP备2023021991号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务