SpringSecurity-Demo 跨域(CORS)配置
-
- 一、什么是跨域问题?
- 二、解决方案:CORS
- [三、Spring Boot 中的两种 CORS 配置方式](#三、Spring Boot 中的两种 CORS 配置方式)
- [✅ 方式一:实现 `WebMvcConfigurer`](#✅ 方式一:实现
WebMvcConfigurer) -
- [🔍 解析:](#🔍 解析:)
- [⚠️ 注意点(重点)](#⚠️ 注意点(重点))
- [✅ 方式二:配置 `CorsConfigurationSource`](#✅ 方式二:配置
CorsConfigurationSource) - [🔍 解析:](#🔍 解析:)
- 四、这两种方式有什么区别?
- [🚨 重点:如果你用了 Spring Security](#🚨 重点:如果你用了 Spring Security)
- 五、推荐最佳实践
-
- [✅ 生产使用时,建议改为白名单:](#✅ 生产使用时,建议改为白名单:)
- [✅ 完整推荐配置:](#✅ 完整推荐配置:)
- 六、常见问题总结
-
- [❌ 1. 跨域仍然报错?](#❌ 1. 跨域仍然报错?)
- [❌ 2. OPTIONS 预检失败?](#❌ 2. OPTIONS 预检失败?)
- [❌ 3. Cookie 不生效?](#❌ 3. Cookie 不生效?)
- [❌ 4. 前端 axios 报错?](#❌ 4. 前端 axios 报错?)
- 七、实战完整配置类
-
- [📌 核心原则:](#📌 核心原则:)
在前后端分离架构中,跨域问题(CORS) 几乎是每个开发者都会遇到的。本文基于一个实际项目中的配置,详细讲解 Spring Boot 中 CORS 的实现方式、原理以及常见坑点。
代码已推送至 Gitee 仓库:springdecurity-demo
一、什么是跨域问题?
浏览器的 同源策略(Same-Origin Policy) 规定:
协议 + 域名 + 端口 必须完全一致,否则就是跨域请求
例如:
| URL | 是否同源 |
|---|---|
| http://a.com/api | ✅ |
| https://a.com/api | ❌(协议不同) |
| http://b.com/api | ❌(域名不同) |
| http://a.com:8080 | ❌(端口不同) |
二、解决方案:CORS
CORS(Cross-Origin Resource Sharing)是浏览器提供的一种机制,通过服务端设置响应头,允许跨域访问。
三、Spring Boot 中的两种 CORS 配置方式
✅ 方式一:实现 WebMvcConfigurer
java
@Override
public void addCorsMappings(CorsRegistry corsRegistry) {
corsRegistry.addMapping("/**")
.allowedOriginPatterns("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600);
}
🔍 解析:
| 配置项 | 说明 |
|---|---|
addMapping("/**") |
对所有接口生效 |
allowedOriginPatterns("*") |
允许所有域(支持通配符) |
allowCredentials(true) |
允许携带 Cookie |
allowedMethods(...) |
允许的 HTTP 方法 |
maxAge(3600) |
预检请求缓存 1 小时 |
⚠️ 注意点(重点)
java
.allowCredentials(true)
.allowedOriginPatterns("*")
👉 这是必须搭配使用的
如果写成:
java
.allowedOrigins("*")
会报错:
When allowCredentials is true, allowedOrigins cannot contain "*"
✅ 方式二:配置 CorsConfigurationSource
java
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOriginPatterns(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
🔍 解析:
| 配置项 | 说明 |
|---|---|
setAllowedOriginPatterns("*") |
允许所有来源 |
setAllowedHeaders("*") |
允许所有请求头 |
setAllowCredentials(true) |
允许 Cookie |
registerCorsConfiguration("/**", ...) |
全局生效 |
四、这两种方式有什么区别?
| 方式 | 使用场景 | 是否推荐 |
|---|---|---|
| WebMvcConfigurer | 简单项目 | ✅ |
| CorsConfigurationSource | 配合 Spring Security | ⭐⭐⭐ 强烈推荐 |
🚨 重点:如果你用了 Spring Security
👉 必须使用 CorsConfigurationSource
并在 Security 中开启:
java
http.cors();
否则:
CORS 配置不会生效!!!
五、推荐最佳实践
⚠️ 当前配置:
java
allowedOriginPatterns("*")
👉 存在安全风险
✅ 生产使用时,建议改为白名单:
java
configuration.setAllowedOriginPatterns(Arrays.asList(
"http://localhost:3000",
"https://your-domain.com"
));
✅ 完整推荐配置:
java
@Configuration
public class CorsConfig {
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOriginPatterns(Arrays.asList(
"http://localhost:3000",
"https://your-domain.com"
));
configuration.setAllowedMethods(Arrays.asList(
"GET", "POST", "PUT", "DELETE", "OPTIONS"
));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowCredentials(true);
configuration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
六、常见问题总结
❌ 1. 跨域仍然报错?
检查:
- 是否使用了 Spring Security
- 是否调用了
http.cors() - 是否被网关(如 Nginx)拦截
❌ 2. OPTIONS 预检失败?
👉 必须允许:
java
.allowedMethods("OPTIONS")
❌ 3. Cookie 不生效?
必须同时满足:
java
.allowCredentials(true)
.allowedOriginPatterns(具体域名,不能用 *)
❌ 4. 前端 axios 报错?
前端也要配置:
js
axios.defaults.withCredentials = true;
七、实战完整配置类
开发环境可以放开,生产环境必须收紧
我在项目中把静态资源映射和跨域配置整合在一起,直接复制就能用:
java
package com.junjiu.springboot3.config;
import com.junjiu.springboot3.config.properties.JunjiuCustomProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Arrays;
/**
* program: security-demo
* ClassName: FileConfig
* description:
*
* @author: 君九
* @create: 2026-04-03 14:33
* @version: 1.0
**/
@Configuration
public class ResourceConfig implements WebMvcConfigurer {
@Autowired
JunjiuCustomProperties junjiuCustomProperties;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String resourcePath = junjiuCustomProperties.getResourcePath();
System.out.println("资源路径:" + resourcePath);
// 确保路径以 / 结尾
if (!resourcePath.endsWith("/")) {
resourcePath += "/";
}
registry.addResourceHandler("/profile/**")
.addResourceLocations("file:" + resourcePath);
}
/**
* 作用对象:Spring MVC 层面的 CORS 配置
* 实现接口:WebMvcConfigurer 接口的方法
* 配置方式:通过 CorsRegistry 配置
* 生效范围:仅适用于 Spring MVC 的 DispatcherServlet 处理的请求
* 配置时机:在 Spring MVC 初始化时注册
* @param corsRegistry
*/
@Override
public void addCorsMappings(CorsRegistry corsRegistry) {
corsRegistry.addMapping("/**")
.allowedOriginPatterns("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600);
}
/**
* 作用对象:Servlet 容器层面的 CORS 配置
* 返回类型:CorsConfigurationSource Bean
* 配置方式:通过 UrlBasedCorsConfigurationSource 配置
* 生效范围:在 Servlet 过滤器链层面生效,对 Spring Security 等过滤器有效
* 配置时机:作为 Bean 被 Spring Security 等组件使用
* @return
*/
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOriginPatterns(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
📌 核心原则:
- 能不用
*就不用 - 有 Security 必须用
CorsConfigurationSource - Cookie 场景必须精准域名
- 代码已推送至 Gitee 仓库:springdecurity-demo
- 若有转载,请标明出处:https://blog.csdn.net/CharlesYuangc/article/details/159804764