본문 바로가기

TIL(Today I Learned)

TIL-230818(항해99 실전 프로젝트-행동대장(13))

📝오늘 공부한 것

  • 실전 프로젝트 - '행동대장'  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

 

OPTIONS - HTTP | MDN

The HTTP OPTIONS method requests permitted communication options for a given URL or server. A client can specify a URL with this method, or an asterisk (*) to refer to the entire server.

developer.mozilla.org

https://www.linkedin.com/pulse/browser-sends-pre-flight-option-request-before-actual-atoconn-india

 

BROWSER SENDS PRE-FLIGHT OPTION REQUEST BEFORE ACTUAL METHOD

The OPTIONS request is so called pre-flight request, which is part of Cross-origin resource sharing (CORS). Browsers use it to check if a request is allowed from a particular domain as follows: The browser wants to send a request, let's say a POST request

www.linkedin.com