Spring Boot 配置跨域(CORS)详解

发表于 2025-08-16 10:45:11 分类于 默认分类 阅读量 66

Spring Boot 配置跨域(CORS)详解

在前后端分离项目中,经常会遇到跨域问题。例如:

Access to XMLHttpRequest at 'https://api.blog.gs/login' from origin 'https://blog.gs' 
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

浏览器安全策略会限制 不同域名/端口/协议 之间的请求,这就是所谓的 同源策略。而 CORS(跨域资源共享,Cross-Origin Resource Sharing)就是为了解决这个问题。


一、常见跨域场景

  • 前端部署在 https://blog.gs
  • 后端 API 部署在 https://api.blog.gs

此时,前端调用后端 API 就会触发跨域。


二、Spring Boot 配置跨域(无 Security)

如果项目中没有使用 Spring Security,只需要实现 WebMvcConfigurer

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("https://blog.gs") // 指定允许的前端域名
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(true) // 是否允许携带 Cookie、Authorization 等凭证
                .maxAge(3600); // 预检请求缓存时间(秒)
    }
}

注意事项

  • 如果使用 allowedOrigins("*")不能再设置 allowCredentials(true),否则无效。
  • 生产环境推荐指定具体域名,而不是 "*"

三、Spring Boot 配置跨域(有 Security)

如果项目使用了 Spring Security,那么上面的 CorsConfig 不会生效,必须在 Security 配置中显式开启 CORS。

示例代码:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.List;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .formLogin().disable()
            .csrf().disable()
            .cors() // ✅ 开启跨域
        .and()
            .authorizeRequests()
            .antMatchers("/admin/**").authenticated()
            .anyRequest().permitAll()
        .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    // ✅ 提供 CORS 配置
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(List.of("https://blog.gs")); // 指定前端域名
        configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(List.of("*"));
        configuration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }
}

四、如何验证 CORS 是否生效?

  1. 浏览器 F12 → Network 面板
  2. 发起 API 请求
  3. 查看 Response Headers 是否包含:
Access-Control-Allow-Origin: https://blog.gs
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true

如果有这些头部,说明 CORS 配置成功。


五、总结

  • 无 Security 项目:实现 WebMvcConfigurer 即可。
  • 有 Security 项目:必须在 HttpSecurity 里启用 .cors(),并提供 CorsConfigurationSource Bean。
  • 生产环境:推荐指定固定域名,而不是 "*",以提升安全性。

这样配置后,前端就可以正常请求后端接口,不再被浏览器拦截。

序章博客
一路向前,山海自平