006-SpringSecurity-Demo 跨域(CORS)配置

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")

必须同时满足:

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 场景必须精准域名

相关推荐
Amctwd18 小时前
【Python】从Excel中按行提取图片
java·python·excel
啃臭18 小时前
AOP和反射
java·spring boot
西凉的悲伤18 小时前
java 使用PNG图片隐写文件
java·图片隐写·png
有梦想的小何18 小时前
Cursor AI 编程实战(篇一):Prompt 与案例总结
java·linux·prompt·ai编程
河阿里18 小时前
SpringBoot:Spring Task定时任务完整使用教学
java·spring boot·spring
jiayong2318 小时前
Tool Permission 与 Sandbox 的安全流水线:Agent 工具系统的工程边界
java·数据库·安全·agent
rururunu18 小时前
Windows 下切换 Java 环境太复杂了,我做了个 cli 工具,可以快速安装,切换 Java 版本
java
qq_4523962318 小时前
第十一篇:《性能压测基础:JMeter线程模型与压测策略设计》
java·开发语言·jmeter
澈20719 小时前
二叉搜索树:高效增删查的秘诀
java·开发语言·算法