[!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); // 允许特殊的请求头
}
};
}