📝오늘 공부한 것
- 실전 프로젝트 - '행동대장' CORS 에러 해결
- 스파르타코딩클럽 심화강의 테스트 코드
⛔문제점
[에러메시지]
Access to XMLHttpRequest at '~~~백엔드 서버 주소~~~' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
-> 프론트에서 CORS 에러 발생
✔ WebSecurityConfig
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// CSRF 설정
http.csrf((csrf) -> csrf.disable());
http.sessionManagement((sessionManagement) ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
);
http.authorizeHttpRequests((authorizeHttpRequests) ->
authorizeHttpRequests
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.requestMatchers("/").permitAll()
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers(HttpMethod.GET, "/api/**").permitAll()
.anyRequest().authenticated()
);
// 필터 관리
http.addFilterBefore(jwtAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
시도해 본 것들💦
✔ WebMvcConfig
@Configuration
@RequiredArgsConstructor
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowCredentials(false)
.allowedHeaders("*")
.exposedHeaders("Authorization")
.allowedOrigins("http://localhost:3000",
"https://front-end-tau-henna.vercel.app",
"https://dev-front-end-omega-henna-44.vercel.app",
"https://test-eta-khaki.vercel.app",
"https://hdaejang.com")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH")
.maxAge(3000);
}
}
.allowedMethods("GET", "POST", "PUT", "DELETE") 에 혹시...?하고 OPTION와 PATCH를 추가해봤다.
그래도 여전히 해결되지 않은 CORS에러..
💯해결
✔ WebSecurityConfig
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// CSRF 설정
http.csrf((csrf) -> csrf.disable());
http.sessionManagement((sessionManagement) ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
);
http.authorizeHttpRequests((authorizeHttpRequests) ->
authorizeHttpRequests
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.requestMatchers("/").permitAll()
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers(HttpMethod.GET, "/api/**").permitAll()
.requestMatchers(HttpMethod.OPTIONS, "/api/**").permitAll()
.anyRequest().authenticated()
);
// 필터 관리
http.addFilterBefore(jwtAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
HTTP 요청 권한을 설정하는 부분에서 메인페이지, 로그인/회원가입, get요청만 허용해주었었다.
그런데 보통 다른 도메인에서 오는 OPTIONS 요청도 인증을 하지 않고 허용해주어햐 한다고 한다.
그래서 .requestMatchers(HttpMethod.OPTIONS,"/api/"*").permitAll() 로 수정하였더니 CORS에러가 해결되었다!
알게 된 점❗
클라이언트의 도메인이 서버의 도메인과 다를 때, 브라우저는 Cross-Origin request를 보호하기 위해 pre-flight request를 보낸다. 이 요청은 Http OPTIONS 메서드로 전송되는데, 서버는 이를 통해 해당 도메인에서 어떤 종류의 요청이 허용되는지를 클라이언트에게 알려줄수 있다.
OPTIONS 요청은 CORS의 일부인 pre-flight request라고 한다.
브라우저에서의 일반적인 요청 흐름
1. 클라이언트가 다른 도메인의 서버로 요청을 보냄
2. 브라우저는 실제 요청 이전에 먼저 OPTIONS 요청을 보내서 서버가 해당 도메인으로 요청을 허용하는 지 확인
3. 서버에서 OPTIONS 요청에 대한 응답으로 CORS 관련 헤더와 함께 허용 여부를 전달
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
https://www.linkedin.com/pulse/browser-sends-pre-flight-option-request-before-actual-atoconn-india
'TIL(Today I Learned)' 카테고리의 다른 글
TIL-230821(OSI 7계층, 세션 기반 인증/토큰 기반 인증) (0) | 2023.08.21 |
---|---|
TIL-230819(항해99 실전 프로젝트-행동대장(14)) (0) | 2023.08.19 |
TIL-230817(항해99 실전 프로젝트-행동대장(12)) (0) | 2023.08.17 |
TIL-230816(ORM, GET/POST) (0) | 2023.08.16 |
TIL-230815(항해99 실전 프로젝트-행동대장(11)) (0) | 2023.08.15 |