在前后端分离的开发模式中,跨域问题是开发者绕不开的一道坎。当您在前端调用后端接口时,是否遇到过浏览器报 Access-Control-Allow-Origin 相关的错误?别慌,这篇文章将带您从原理到实战,彻底解决 Spring Boot 项目的跨域问题。
一、跨域是什么?为什么会有跨域问题?
1. 什么是跨域?
跨域是指浏览器的同源策略限制,当请求的协议、域名、端口三者中任意一个与当前页面不同时,就会触发跨域。
举个例子:
·前端页面地址:http://localhost:8080
·后端接口地址:https://api.zetcher.com
此时协议(http vs https)、域名(localhost vs api.zetcher.com)均不同,属于跨域请求。
2. 为什么浏览器要限制跨域?
这是浏览器的安全机制,防止恶意网站通过脚本窃取其他网站的敏感数据(如 Cookie、Token 等)。但在前后端分离的合法场景下,我们需要主动配置允许跨域。
二、Spring Boot 如何优雅配置跨域?
下面结合实际代码,讲解两种常用的跨域配置方式。
方式 1:全局跨域过滤器(推荐)
通过自定义 CorsFilter,实现全局跨域控制,这是 Spring Boot 中最灵活的方案。
步骤 1:编写跨域配置类
package com.zetcher.platjava.config;
import org.springframework.beans.factory.annotation.Value;
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 {
// 从配置文件读取允许跨域的域名列表(分号分隔)
@Value("${CorOrigin:http://localhost:5000;http://localhost;http://fms.zetcher.com:6030}")
private String corOrigin;
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
if (corOrigin.contains("*")) {
// 通配符*:允许所有域名(适合开发环境,生产慎用)
config.addAllowedOriginPattern("*");
config.setAllowCredentials(false); // 允许所有源时,通常不携带凭证
} else {
// 精确配置允许的域名
String[] origins = corOrigin.split(";");
for (String origin : origins) {
if (!origin.trim().isEmpty()) {
config.addAllowedOrigin(origin.trim());
}
}
config.setAllowCredentials(true); // 特定域名允许携带凭证(如Cookie)
}
// 允许所有HTTP方法(GET、POST、PUT、DELETE等)
config.addAllowedMethod("*");
// 允许所有请求头(如Token、Content-Type等)
config.addAllowedHeader("*");
// 跨域请求有效期(可选,默认30分钟)
// config.setMaxAge(1800L);
// 对所有路径生效
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
步骤 2:配置文件中定义允许的域名
在 application.yml 中添加:
CorOrigin:https://fms.zetcher.com:6030;http://192.168.90.151:3301; http://localhost:8080
方式 2:注解式配置(局部接口)
如果只需对个别接口允许跨域,可使用 @CrossOrigin 注解。
@RestController
@RequestMapping("/api")
public class DemoController {
// 仅对该接口允许跨域
@CrossOrigin(origins = "https://fms.zetcher.com:6030")
@GetMapping("/hello")
public String hello() {
return "跨域请求成功!";
}
}
三、生产环境跨域配置的最佳实践
1. 安全优先:避免使用通配符*
生产环境中,应精确配置允许的域名列表,避免 * 带来的安全风险。例如:
在 application.yml 中
CorOrigin: https://fms.zetcher.com:6030;https://kitty.zetcher.com:5002
2. 携带凭证的跨域请求
如果前端需要携带 Cookie 或 Token,需注意:
·后端配置 config.setAllowCredentials(true);
·前端请求需设置 withCredentials: true(如 Axios 中配置)。
3. 跨域配置的可视化提示
可以通过自定义监听器,在项目启动时输出跨域配置信息,方便排查问题:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@Component
public class ServerConfig implements ApplicationListener
private final Environment env;
@Value("${CorOrigin:}")
private String corOrigin;
public ServerConfig(Environment env) {
this.env = env;
}
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
// 输出跨域配置信息
if (corOrigin.contains("*")) {
System.err.println("警告: 允许所有域名访问存在安全风险,建议配置具体域名清单!");
} else if (!corOrigin.isEmpty()) {
System.out.println("当前允许跨域的域名:" + corOrigin);
}
}
}
四、常见问题与排查技巧
1. 配置了跨域但仍报错?
·检查前端请求是否携带了 withCredentials: true,而后端未配置 allowCredentials: true;
·确认域名是否包含端口(如 https://fms.zetcher.com 和 https://fms.zetcher.com:6030 是两个不同的域名);
·查看浏览器控制台的 Network 面板,检查响应头是否包含 Access-Control-Allow-Origin。
2. 多个跨域配置冲突?
Spring Boot 中全局过滤器优先级高于注解式配置,若同时存在,以全局配置为准。建议统一使用全局过滤器管理跨域。
五、总结
跨域问题是前后端分离开发的必经之路,通过 Spring Boot 的 CorsFilter 可轻松实现灵活、安全的跨域控制。记住以下几点:
·开发环境可临时用 * 快速调试,生产环境必须精确配置域名;
·携带凭证的请求需同时配置 allowCredentials: true;
·结合启动提示和浏览器调试工具,快速定位问题。
掌握这些技巧,让您的 Spring Boot 项目彻底告别跨域烦恼!

