드디어 배포된 스프링 부트 API를 프론트팀이 연결하는 과정이었다.
그런데 계속 Cors 에러가 떴다.
엄청난 시간동안 머리를 싸맸는데 결론은 시시콜콜한 문제였다.
영광의 삽질을 기록한다.
1. 이름만 같은 CorsFilter, 넌 누구냐 임마
내 프로젝트는 CorsConfig에서 CorsFilter를 정의해서 사용했다.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.addAllowedOrigin("*");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
source.registerCorsConfiguration("/**", configuration);
return new CorsFilter(source);
}
}
그런데 프론트에서는 계속 Cors에러가 나고, 상황 자체가 내 CorsConfig와 너무 달랐다.
즉, CorsConfig가 안먹히고 있다는 의미였다.
원인을 찾아다니던 중, 내 SecurityConfig에 낯선 CorsFilter가 들어앉아 있는 것을 잡아냈다.
import org.springframework.web.filter.CorsFilter; ??????
import org.springframework.web.filter.CorsFilter; // ????
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final CorsFilter corsFilter; // 뉘슈?
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.addFilter(corsFilter)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
결국 내가 만든 CorsConfig의 CorsFilter로 정확히 넣어주니까 정상적으로 CorsFilter가 작동했다.
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final CorsConfig corsConfig;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.addFilter(corsConfig.corsFilter()) // 내 corsFilter !
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
2. PreFlight 설정
아직 PreFlight에 대하여 정확히 공부하지는 못했지만, 대략적인 개념만 알아보게 되었다.
프론트가 서버로 요청을 보내기 전, OPTION으로 테스트 요청을 먼저 보내보고 그 요청이 정상처리되면 진짜 요청을 보내는 과정이라고 한다.
따라서 Spring Security에서 Method (GET, POST 등)에 OPTION을 추가해주고, isPreFlight 요청은 무조건 permitAll 해주었다.
// SecurityConfig
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.addFilter(corsConfig.corsFilter())
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests()
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll() // 추가
.antMatchers(HttpMethod.OPTIONS).permitAll() // 추가
.
.
.
}
'Cloud, Infra > Deploy' 카테고리의 다른 글
[React & Spring Boot] 클라이언트 배포(1) : Route 53, EC2 (0) | 2023.05.05 |
---|---|
[React] EC2 인스턴스에 React 프로젝트 배포 (0) | 2023.05.03 |
[Deploy] 배포된 EC2에서 Google Login이 안되는 문제 해결 (0) | 2023.03.02 |
[Deploy] EC2에서 Redis 사용하기 (0) | 2023.03.02 |
[Deploy] Github Actions + Docker + EC2 자동 배포 #2 | Docker 설정 (0) | 2023.02.28 |