Gymterview
middle

Что такое CORS и как его настроить в Spring?

CORS (Cross-Origin Resource Sharing) — механизм безопасности браузера, который контролирует, какие домены могут обращаться к ресурсам API. По умолчанию браузеры запрещают JavaScript-коду делать запросы к другому домену (Same-Origin Policy).

Как работает CORS

Простые запросы (GET, HEAD, POST с простыми заголовками) — браузер отправляет запрос напрямую с заголовком Origin:

Пример
GET /api/users HTTP/1.1
Origin: https://frontend.example.com

Ответ:
Access-Control-Allow-Origin: https://frontend.example.com

Предварительные запросы (Preflight) — для «сложных» запросов (PUT, DELETE, кастомные заголовки) браузер сначала отправляет OPTIONS:

Пример
OPTIONS /api/users/42 HTTP/1.1
Origin: https://frontend.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type, Authorization

Ответ:
Access-Control-Allow-Origin: https://frontend.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 3600

Настройка в Spring

Три способа настройки CORS
  1. Аннотация на контроллере:
@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = "https://frontend.example.com")
public class UserController {

    @CrossOrigin(origins = "*", maxAge = 3600)
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) { ... }
}
  1. Глобальная конфигурация через WebMvcConfigurer:
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
            .allowedOrigins("https://frontend.example.com")
            .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE")
            .allowedHeaders("*")
            .allowCredentials(true)
            .maxAge(3600);
    }
}
  1. Через Spring Security (если используется):
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
        .cors(cors -> cors.configurationSource(corsConfigurationSource()))
        .csrf(csrf -> csrf.disable())
        .build();
}

@Bean
public CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowedOrigins(List.of("https://frontend.example.com"));
    config.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE"));
    config.setAllowedHeaders(List.of("*"));
    config.setAllowCredentials(true);

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

Если используется Spring Security, настройку CORS нужно делать через SecurityFilterChain, так как Spring Security обрабатывает запросы раньше WebMvcConfigurer.

На собеседовании: нужно объяснить, зачем нужен CORS (Same-Origin Policy), что такое preflight-запрос и как настроить в Spring. Частая ошибка — ставить allowedOrigins("*") в продакшне вместо конкретных доменов.