SpringBoot2.6.13+Java8跨域配置实践
更新时间:2026年03月13日 14:20:19 作者:bug攻城狮
文章介绍了三种跨域配置方案,并对比了它们的优缺点,方案一和方案二适用于开发环境,方案三适用于生产环境,如果使用SpringSecurity,推荐使用方案二,如果需要携带凭证,将allowCredentials设置为true
方案一:基于WebMvcConfigurer的配置
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 全局跨域配置类
* <p>
* 说明:
* 1. 使用 @Configuration 注解,让 Spring 在启动时加载此配置
* 2. 实现 WebMvcConfigurer 接口,重写 addCorsMappings 方法
* 3. 适用于 Spring MVC 项目
* <p>
* 注意:
* - 如果项目中同时使用了 Spring Security,需要在 Security 配置中允许跨域
* - 生产环境请将 allowedOriginPatterns 替换为具体的域名,不要使用 "*"
*/
@Configuration
public class GlobalCorsConfig implements WebMvcConfigurer {
// 定义允许的方法常量
private static final String[] ALLOWED_METHODS = {
"GET", // 读取
"POST", // 创建
"PUT", // 完全更新
"PATCH", // 部分更新
"DELETE", // 删除
"OPTIONS" // CORS 预检请求(必须)
};
/**
* 配置跨域规则
*
* @param registry CORS 注册器,用于配置跨域规则
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
// 添加跨域映射规则
registry.addMapping("/**") // 匹配所有请求路径
// 允许的源(域名)配置
// 注意:当 allowCredentials 为 true 时,不能使用 "*"
// 开发环境可以使用通配符,生产环境请替换为具体域名
.allowedOriginPatterns("*")
// 允许的 HTTP 方法
.allowedMethods(ALLOWED_METHODS)
// 允许的请求头
// 如果前端需要携带自定义头,需要在这里添加,如 "X-Token"
.allowedHeaders("*")
// 是否允许携带凭证(如 Cookies、Authorization 头等)
// 注意:如果设置为 true,则 allowedOriginPatterns 不能为 "*"
.allowCredentials(false)
// 预检请求的缓存时间(单位:秒)
// 在这个时间内,同一请求的预检请求不再发送
.maxAge(3600)
// 暴露给前端的响应头
// 如果前端需要访问某些自定义响应头,需要在这里暴露
.exposedHeaders("Authorization", "X-Token");
}
}
方案二:基于CorsFilter的配置(更灵活)
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;
import java.util.Arrays;
/**
* 基于 CorsFilter 的跨域配置
* <p>
* 优点:
* 1. 优先级更高,会在 Spring Security 之前执行
* 2. 可以更灵活地配置,支持动态源
* 3. 适用于所有请求,包括静态资源
* <p>
* 适用场景:
* 1. 需要更细粒度的跨域控制
* 2. 项目同时使用了 Spring Security
* 3. 需要根据请求动态判断是否允许跨域
*/
@Configuration
public class CorsFilterConfig {
// 定义允许的方法常量
private static final String[] ALLOWED_METHODS = {
"GET", // 读取
"POST", // 创建
"PUT", // 完全更新
"PATCH", // 部分更新
"DELETE", // 删除
"OPTIONS" // CORS 预检请求(必须)
};
/**
* 创建 CorsFilter Bean
*
* @return CorsFilter 跨域过滤器
*/
@Bean
public CorsFilter corsFilter() {
// 创建 CORS 配置对象
CorsConfiguration config = new CorsConfiguration();
// 设置是否允许携带凭证
// 注意:如果设置为 true,则不能使用 addAllowedOrigin("*")
config.setAllowCredentials(false);
// 设置允许的源(域名)
// 开发环境可以使用 "*",生产环境请替换为具体域名
config.addAllowedOriginPattern("*");
// 设置允许的 HTTP 方法
config.setAllowedMethods(Arrays.asList(ALLOWED_METHODS));
// 设置允许的请求头
config.setAllowedHeaders(Arrays.asList(
"Origin", "Content-Type", "Accept", "Authorization",
"X-Requested-With", "X-Token", "Cache-Control"
));
// 设置暴露给前端的响应头
config.setExposedHeaders(Arrays.asList(
"Authorization", "X-Token", "Content-Disposition"
));
// 设置预检请求的缓存时间(单位:秒)
config.setMaxAge(3600L);
// 创建基于 URL 的 CORS 配置源
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// 注册 CORS 配置,应用到所有路径
source.registerCorsConfiguration("/**", config);
// 创建并返回 CorsFilter
return new CorsFilter(source);
}
}
方案三:生产环境推荐配置(带环境区分)
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;
import java.util.Arrays;
import java.util.List;
/**
* 生产环境跨域配置(带环境区分)
* <p>
* 特点:
* 1. 通过配置文件区分开发和生产环境
* 2. 开发环境允许所有源,生产环境只允许指定域名
* 3. 支持多个允许的域名
*/
@Configuration
public class EnvironmentBasedCorsConfig {
// 定义允许的方法常量
private static final String[] ALLOWED_METHODS = {
"GET", // 读取
"POST", // 创建
"PUT", // 完全更新
"PATCH", // 部分更新
"DELETE", // 删除
"OPTIONS" // CORS 预检请求(必须)
};
/**
* 应用运行环境
* 在 application.yml 中配置:env: dev/prod
*/
@Value("${env:dev}")
private String environment;
/**
* 生产环境允许的域名列表
* 在 application.yml 中配置:cors.allowed-origins: https://domain1.com,https://domain2.com
*/
@Value("${cors.allowed-origins:}")
private List<String> allowedOrigins;
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// 根据环境设置不同的配置
if ("prod".equalsIgnoreCase(environment)) {
// 生产环境配置
config.setAllowCredentials(true);
// 设置允许的具体域名
if (allowedOrigins != null && !allowedOrigins.isEmpty()) {
allowedOrigins.forEach(config::addAllowedOriginPattern);
} else {
// 如果没有配置,默认不允许任何跨域(安全考虑)
config.addAllowedOriginPattern(""); // 空字符串表示不允许
}
} else {
// 开发/测试环境配置
config.setAllowCredentials(false);
config.addAllowedOriginPattern("*");
}
// 公共配置
config.setAllowedMethods(Arrays.asList(ALLOWED_METHODS));
config.setAllowedHeaders(Arrays.asList(
"Origin", "Content-Type", "Accept", "Authorization",
"X-Requested-With", "X-Token", "Cache-Control"
));
config.setExposedHeaders(Arrays.asList("Authorization", "X-Token"));
config.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
对应的application.yml配置
# 应用配置 spring: application: name: your-application-name # 跨域配置(用于方案三) env: dev # 环境:dev-开发,prod-生产 # 生产环境允许的域名(多个用逗号分隔) cors: allowed-origins: https://www.yourdomain.com, https://api.yourdomain.com, http://localhost:3000 # 开发时保留
编码规则说明
这里以HTTP方法的跨域规则为例说明,其他所有可使用通配符的配置都是如此:
// 不推荐:过于宽松
config.addAllowedMethod("*");
// 推荐:明确列出需要的 HTTP 方法
config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
| 对比项 | 通配符* | 具体方法列表 |
|---|---|---|
| 安全性 | 较低(允许所有方法) | 较高(最小权限原则) |
| 清晰度 | 不明确允许哪些方法 | 明确列出允许的方法 |
| 兼容性 | 浏览器都支持 | 浏览器都支持 |
| 维护性 | 简单但模糊 | 清晰易于维护 |
| 推荐度 | ⭐⭐☆☆☆ | ⭐⭐⭐⭐⭐ |
使用建议
- 开发环境:使用方案一或方案二,配置简单
- 生产环境:使用方案三,严格控制允许的域名
- 如果使用 Spring Security:推荐使用方案二(CorsFilter),因为它的执行顺序更靠前
如果需要携带凭证(如 Cookies):
- 将
allowCredentials设置为true - 将
allowedOriginPatterns("*")改为具体的域名列表
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
mybatis-plus的selectById(或者selectOne)在根据主键ID查询实体对象的时候偶尔会出现nul
这篇文章主要介绍了mybatis-plus的selectById(或者selectOne)在根据主键ID查询实体对象的时候偶尔会出现null的问题记录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-09-09
SpringMVC加载控制与Postmand的使用和Rest风格的引入及RestFul开发全面详解
SpringMVC是一种基于Java,实现了Web MVC设计模式,请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将Web层进行职责解耦。基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,SpringMVC也是要简化我们日常Web开发2022-10-10
SpringBoot favicon Chrome设置问题解决方案
在本篇文章里小编给大家分享的是关于SpringBoot favicon Chrome设置问题实例内容,小的朋友们可以参考学习下。2020-02-02
AbstractQueuedSynchronizer内部类Node使用讲解
这篇文章主要为大家介绍了AbstractQueuedSynchronizer内部类Node使用讲解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-07-07
SpringBoot项目nohup启动运行日志过大的解决方案
这篇文章主要介绍了SpringBoot项目nohup启动运行日志过大的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-05-05
SpringBoot自定义MessageConvert详细讲解
正在学习SpringBoot,在自定义MessageConverter时发现:为同一个返回值类型配置多个MessageConverter时,可能会发生响应数据格式错误,或406异常(客户端无法接收相应数据)。在此记录一下解决问题以及追踪源码的过程2023-01-01


最新评论