Skip to content

[!quote] 跨域 以下条件不满足其一,即为跨域 :

  • 不同域名 :https://example.com 访问 https://api.example.net
  • 不同端口 :https://example.com:8080 访问 https://example.com:9090
  • 不同协议 :http://example.com 访问 https://example.com

在 Spring Boot 中配置 CORS 跨域资源共享 有几种方法,每种方法的应用场景和效果略有不同:

  • CorsConfigurationSource 适合需要细粒度控制,或者与 Spring Security 配置结合的场景
  • @CrossOrigin 适合简单场景,单个控制器或方法需要跨域访问时使用
  • 全局配置 CORS 适合全局统一的 CORS 配置需求,最为简洁

CorsConfigurationSource

这种方式是在 Spring Security 配置类中定义一个 CorsConfigurationSource bean,并在 HttpSecurity 配置中启用 CORS

java
@Bean
public CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("http://localhost:8080")); // 前端地址
    configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
    configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type"));
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

SecurityConfig 中启用 CORS:

java
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .cors(withDefaults())
            .csrf().disable() // 根据需要启用或禁用CSRF
            .authorizeRequests(authorizeRequests ->
                authorizeRequests
                    .antMatchers("/login", "/oauth2/**", "/public/**").permitAll()
                    .anyRequest().authenticated()
            )
            .formLogin(formLogin ->
                formLogin
                    .loginPage("/login")
                    .defaultSuccessUrl("/home")
                    .permitAll()
            )
            .oauth2Login(oauth2Login ->
                oauth2Login
                    .loginPage("/login")
                    .defaultSuccessUrl("/home")
            )
            .logout(logout ->
                logout
                    .logoutSuccessHandler(logoutSuccessHandler())
                    .permitAll()
            );
        return http.build();
    }
}
  • 细粒度控制,可以为不同的路径设置不同的 CORS 规则
  • 可以结合 Spring Security 的其他配置一起使用
  • 配置稍微复杂,需要定义额外的 Bean

@CrossOrigin 注解

@CrossOrigin 注解可以直接在控制器方法或类上使用,允许特定的路径进行跨域请求。

在控制器类或方法上使用:

java
@RestController
@CrossOrigin(origins = "http://localhost:8080")
public class MyController {

    @GetMapping("/example")
    public String example() {
        return "Example response";
    }
}
  • 简单直接,只需要在需要跨域的控制器或方法上添加注解
  • 缺乏全局配置的灵活性,需要在每个需要跨域的地方单独添加注解

全局配置

  • 无需在每个控制器或方法上添加注解
  • 可能与 Spring Security 的配置发生冲突,需要小心处理
java
@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedOrigins("http://localhost:8080")
                    .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD", "TRACE")
                    .allowedHeaders("*")  // 允许的请求头
                    .allowCredentials(true);  // 允许特殊的请求头
        }
    };
}