一、为什么需要跨域配置?

浏览器有一条安全策略:页面里的 JavaScript 不能随便访问「另一个网站」的接口。

举个常见场景:

  • 前端页面部署在:https://a.com
  • 后端接口在:https://api.b.com

用户在 a.com 打开页面,前端用 fetch / axios 去请求 api.b.com。这时浏览器会先做一件事:向 api.b.com 确认——是否允许来自 a.com 的跨站访问。
这种「先问能不能」的机制,就是 CORS(Cross-Origin Resource Sharing,跨域资源共享)。

后端如果什么都不配,浏览器可能直接拦截请求,前端控制台出现类似 blocked by CORS policy 的报错。

你在 Spring 里写的 CorsConfig,作用就是:配合浏览器完成 CORS 检查,并声明:允许哪些来源、哪些 HTTP 方法、哪些请求头、是否允许带 Cookie 等。

补充: CORS 只约束「浏览器里的网页脚本」。用 Postman、curl、服务端互相调用,不走这套规则,所以会出现「Postman 能通、浏览器报跨域」的现象,这是正常的。


二、示例代码:全局 CORS 配置


/**
 * 全局跨域配置
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 覆盖所有请求
        //** 表示:本项目里几乎所有路径(所有 Controller 的接口)都应用这套跨域规则。
        registry.addMapping("/**")
                // 允许发送 Cookie
                .allowCredentials(true)
                // 放行哪些域名(必须用 patterns,否则 * 会和 allowCredentials 冲突)
                .allowedOriginPatterns("*")
                // 放行哪些请求方式2
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                //允许前端带哪些请求头
                .allowedHeaders("*")
                // 暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
                .exposedHeaders("*");
    }
}

下面按「这段代码在干什么」逐块说明。


三、@Configuration 与 WebMvcConfigurer

  • @Configuration:声明这是一个 Spring 配置类,会在应用启动时被加载,里面的 Bean / 配置会生效。
  • implements WebMvcConfigurer:实现 Spring MVC 提供的扩展接口,通过重写方法定制 Web 行为,例如:
    • 跨域(CORS)
    • 拦截器
    • 静态资源映射
    • 消息转换器等

这里重写的是 addCorsMappings,专门用于 跨域规则。


四、registry.addMapping("/**"):对哪些路径生效?

  • /**:表示项目里 几乎所有 URL 都会应用这套 CORS 规则(通常等价于「所有 Controller 接口」)。

若只想开放部分接口,可以写成更细的路径,例如 /api/**


五、allowCredentials(true):是否允许携带凭证?

凭证常见包括:

  • Cookie(会话、登录态)
  • 某些场景下与认证相关的设置

设为 true 表示:当前端使用例如:

  • fetch(url, { credentials: 'include' })
  • 或 axios:withCredentials: true

浏览器可以把 Cookie 等凭证 一并发给后端,且后端在 CORS 策略上 允许 这类请求。

注意: 一旦开启 allowCredentials(true),浏览器对「允许的来源」会更严格。历史上若用 allowedOrigins("*") 搭配凭证,容易和规范冲突。因此 Spring 里常用 allowedOriginPatterns 等方式,在需要凭证时更灵活地配置来源(见下一节)。


六、allowedOriginPatterns("*"):允许哪些「来源」?

**来源(Origin)**可以理解为:用户当前页面所在的站点,例如 https://a.com

  • "*"(pattern) 在这里表示:任意来源 的页面都可以跨域访问你的接口(在开发与内网环境很方便)。

和 allowedOrigins("*") 的差异(通俗理解):

  • allowedOriginPatterns 支持模式匹配,且在 需要凭证 时,比简单写死 * 更容易符合实际使用方式。

生产环境提醒: * 非常宽松,任意网站的页面都可能让用户浏览器去请求你的接口。若同时还允许带 Cookie,被恶意站点滥用的风险会上升。线上常见做法是改为 白名单域名(例如只允许 https://www.xxx.comhttps://admin.xxx.com)。


七、allowedMethods(...):允许哪些 HTTP 方法?

这里列出了:GETPOSTPUTDELETEOPTIONS

为什么要包含 OPTIONS

对「非简单请求」,浏览器往往会先发一个 OPTIONS 预检请求(preflight),询问服务器:接下来我要用某种方法、带某些头,你是否允许?
若后端没有把 OPTIONS 配进允许的方法,预检可能失败,真正的 POST 等请求就不会发出去。


八、allowedHeaders("*"):允许哪些请求头?

* 表示:允许客户端携带任意请求头(在允许的范围内),例如:

  • Content-Type(如 application/json
  • Authorization
  • 业务自定义头

若这里配置过窄,而前端多带了某个头,可能导致 预检失败。


九、exposedHeaders("*"):暴露哪些响应头给前端 JS?

默认情况下,浏览器 只允许 JavaScript 读取部分标准响应头。
如果后端设置了自定义响应头(例如分页总数 X-Total-Count、文件下载名等),前端脚本要读取,就需要在 CORS 中 声明暴露(expose) 这些头。

* 在这里表示:尽可能把可暴露的响应头开放给前端(具体以 Spring 版本与实现为准)。


十、两个常见「坑」小结

现象 说明

Postman 正常,浏览器跨域

CORS 是浏览器策略;Postman 不模拟浏览器的同源限制。

allowedOriginPatterns("*") 过于宽松

学习/内网可用;公网 API 建议改成 明确域名白名单,并结合业务评估是否必须 allowCredentials(true)


十一、一句话总结

这段 CorsConfig 的含义可以概括为:

对本服务几乎所有路径开放跨域访问;允许常见 HTTP 方法(含 OPTIONS 预检);允许任意请求头、暴露响应头;并允许浏览器在跨域场景下携带 Cookie 等凭证;来源暂时放行任意站点(*)。

结语: 跨域配置是前后端分离项目的「标配」之一。理解 CORS 是浏览器行为、分清开发环境与生产环境的风险,再选择合适的来源白名单,才能既方便调试又保证安全。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐