方案一:基于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("*")改为具体的域名列表
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论