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

相关推荐
2601_949817922 小时前
spring-ai 下载不了依赖spring-ai-openai-spring-boot-starter
java·人工智能·spring
迷藏4942 小时前
**发散创新:基于Python与深度学习的情绪识别实战全流程解析**在人工智能快速发展的今天,**情绪识别(Emoti
java·人工智能·python·深度学习
Ashore11_2 小时前
蓝桥杯16届Java研究生组
java·算法·蓝桥杯
东离与糖宝2 小时前
Spring AI 2.0+Gemma 4端侧部署:Java离线AI应用全教程
java·人工智能
0xDevNull2 小时前
Java BigDecimal 完全指南:从入门到精通
java·开发语言·后端
ch.ju2 小时前
Java程序设计(第3版)第二章——变量的三种定义方式1
java
XiYang-DING2 小时前
【Java】从源码深入理解LinkedList
java·开发语言
无心水2 小时前
17、Java内存溢出(OOM)避坑指南:三个典型案例深度解析
java·开发语言·后端·python·架构·java.time·java时间处理
冰暮流星2 小时前
javascript之Dom查询操作1
java·前端·javascript