난 백엔드 개발자이다.
그런데 내가 만든 API가 웹 브라우저에서 어떻게 동작하는지 알고 싶어졌다.
그래서 자바스크립트와 HTML로 간단하게 로그인 페이지를 만들어서 테스트 해보는 중 콘솔에 메세지가 떴다.
Preflight response is not successful. Status code: 403
Fetch API cannot load http://13.125.249.67:8080/user/login due to access control checks.
왜 이런 메세지가 떴을까?
지금 나는 프론트엔드 서버와 백엔드 서버를 분리해놨다.
백엔드 서버는 spring boot로 만들었다. 이건 곧 Web Application Server = WAS이다.
프론트엔드 서버는 로컬에서 실행되도록 만들었다.
웹 브라우져는 웹서버에서 받은 정적 데이터로 이루어져 있고
웹 브라우져에서 내가 만든 기능들을 이용하려면 웹 서버 -> WAS 이렇게 요청이 가야한다.
그런데 만약 웹 서버에서 WAS로 아무런 허가 없이 요청이 가게된다면?
전 세계 특정 프론트엔드 서버에서 내가 만든 WAS로 마구잡이로 요청을 보내게 될것이다.
특정 웹서버와 WAS만 연결되어 있음을 설정해줘야 하는 것이다.
브라우저는 실제로 CORS(Cross-Origin Resource Sharing) 정책을 적용하기 위해 사전 요청(Preflight Request)을 보내기 전에 간단한 요청(Simple Request)을 사용하여 서버에 직접 요청을 보냅니다.
만약 여기서 CORS 정책이 설정되지 않은 경우, 브라우저는 보안상의 이유로 다른 출처(origin)로부터의 리소스 요청을 차단하게 된다.
즉, 이 문제는 내가 webconfig에 cors 설정을 하지 않았기 때문이다.
해결
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.cors(corsCustomize -> corsCustomize.configurationSource(request -> {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOriginPatterns(Collections.singletonList("*"));
config.addAllowedMethod(HttpMethod.OPTIONS);
config.addAllowedMethod(HttpMethod.GET);
config.addAllowedMethod(HttpMethod.POST);
config.addAllowedMethod(HttpMethod.PUT);
config.addAllowedMethod(HttpMethod.DELETE);
config.addAllowedHeader("Content-Type");
config.setMaxAge(3600L);
return config;
}))
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/**").permitAll()
.anyRequest().authenticated())
.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
cors 설정을 추가해주었다. 테스트 용이기 때문에 일단은 config.setAllowedOriginPatterns(Collections.singletonList("")); 해놨다. 나중에 프론트엔드 서버가 구축되면 ""를 대신해서 프론트엔드서버를 넣으면 되는 것이다.
그리고 순서가 중요하다. 왜냐면 브라우져는 cors 정책이 있는지 먼저 확인하기 때문이다.
이렇게해서 일단은 로컬에서 간단하게 만든 HTML로 로그인 테스트를 성공하였다.