Post

SpringBoot(백엔드), React(프론트엔드) 사이 CORS 문제

SpringBoot(백엔드), React(프론트엔드) 사이 CORS 문제

SpringBoot(백엔드), React(프론트엔드) 사이 CORS 문제

서버는 스프링부트이고, 프론트 단은 React를 사용하였는데 서버에 Request를 요청할 때 CORS 에러가 발생했다.

CORS는 무엇일까?

교차 출처 리소스 공유를 뜻하는 CORS는 서로 다른 출처에서 리소스를 공유하는 것을 뜻한다.

cors란?

여기서 출처란 다음의 사진을 보자.

1

URL은 https://www.domain.com:3000/user?query=name&page=1와 같은 형태로 이루어져 있다.

여기서 Protocol, Host, Port를 합쳐서 부르는 말이 Origin(출처)이다.

CORS 허용 설정을 하지 않으면 서버와 다른 Origin을 가진 곳에서 서버의 Origin에 요청을 보내면 CORS 에러가 발생한다.

프로젝트를 하며 CORS 에러가 발생했다.

1

1
Access to fetch at 'http://localhost:8080/api/users/login' 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. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
1
2
3
4
5
6
7
8
9
10
11
12
13
@Configuration  
public class WebSecurityConfig implements WebMvcConfigurer {  
  
    @Override  
  public void addCorsMappings(CorsRegistry registry) {  
        registry  
                .addMapping("/**")  
                .allowedOrigins("http://localhost:3000")  
                .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")  
               
  }  
  
}

보통은 다음과 같이 addCorsMappings 메서드를 오버라이딩하여 모든 RequestMapping에 대하여 통신을 주고 받는 React Origin의 요청에 대해 CORS를 허용하면 됐었다.

하지만 이런 방법으로는 해결되지 않았다..😂

SecurityConfig 파일에서 다음을 추가해 주면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
@Bean
public CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.addAllowedOrigin("http://localhost:3000"); // 허용할 프론트엔드 도메인
    configuration.addAllowedMethod("*"); // 모든 HTTP 메서드 허용
    configuration.addAllowedHeader("*"); // 모든 헤더 허용
    configuration.setAllowCredentials(true); // 인증 정보를 포함한 요청 허용
    configuration.addExposedHeader("Authorization");
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration); // 모든 경로에 대해 설정 적용

    return source;
}
  • addAllowedOrigin("http://localhost:3000"): localhost:3000에서 온 요청만 허용.
  • addAllowedMethod("*"): 모든 HTTP 메서드 (GET, POST 등)를 허용.
  • addAllowedHeader("*"): 모든 헤더를 허용.
  • setAllowCredentials(true): 인증 정보(예: 쿠키)를 포함한 요청을 허용.
  • configuration.addExposedHeader("Authorization")를 하지 않으면 프론트 단에서 Authosization 값이 null로 표시돼서 추가하고 해결;

그 후에 CORS 설정을 httpSecurity에 적용한다.

1
httpSecurity.cors((cors) -> cors.configurationSource(corsConfigurationSource()));

이로 인해 httpSecurity는 클라이언트에서 오는 요청에 대해 CORS 정책을 체크하고 처리한다!

1

다음과 같이 Network > Response Headers에 잘 담긴 것을 확인할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Bean  
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {  
    httpSecurity.csrf((csrf) -> csrf.disable());  
  
    httpSecurity.sessionManagement((sessionManagement) ->  
            sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)  
    );  
  
    httpSecurity.authorizeHttpRequests((authorizeRequest) ->  
            authorizeRequest  
                    .requestMatchers("/api/users/login").permitAll()  
                    .anyRequest().authenticated()  
    ).cors((cors) -> cors.configurationSource(corsConfigurationSource()));  
  
    httpSecurity.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);  
    httpSecurity.addFilterAfter(jwtAuthorizationFilter(), JwtAuthenticationFilter.class);  
  
    return httpSecurity.build();  
}

계속 httpSecurity.cors()로 해서 오류가 났었다..😓

This post is licensed under CC BY 4.0 by the author.