TIL

백 & 프론트 협업시 발생하는 CORS에러 해결 방법.

Big Iron 2023. 3. 20. 18:00

프로젝트 배포하기 위해 먼저 거쳐야 하는 것은 프론트와 백의 소스를 합치는 일이다.
이러한 과정에서 발생하는 대표적인 문제는 CORS에러이다.

 

CORS는 Cross-Origin Resource Sharing 이라는 단어로 이루어 져 있고. 문장을 직역하면 "교차 출처 리소스 공유 정책"이라고 해석할 수 있다. 교차 출처란 엇갈린 다른 출처를 의미하는 것으로 보면 된다.

 

분명 따로 개발하고 기능을 돌려봤을 때 문제는 없었지만 발생한 CORS를 해결하기 위해 WebSecurityConfig 클래스에 코드를 추가했다. 원래 코드는 아래와 같다.

  package com.sparta.studybook.config;

  import com.sparta.studybook.jwt.JwtAuthFilter;
  import com.sparta.studybook.jwt.JwtUtil;
  import lombok.RequiredArgsConstructor;
  import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.http.HttpMethod;
  import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
  import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
  import org.springframework.security.config.http.SessionCreationPolicy;
  import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  import org.springframework.security.crypto.password.PasswordEncoder;
  import org.springframework.security.web.SecurityFilterChain;
  import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
  import org.springframework.web.cors.CorsConfiguration;
  import org.springframework.web.cors.CorsConfigurationSource;
  import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

  @Configuration
  @RequiredArgsConstructor
  @EnableWebSecurity // 스프링 Security 지원을 가능하게 함
  @EnableGlobalMethodSecurity(securedEnabled = true) // @Secured 어노테이션 활성화
  public class WebSecurityConfig {

      private final JwtUtil jwtUtil;

      @Bean
      public PasswordEncoder passwordEncoder() {
          return new BCryptPasswordEncoder();
      }


      @Bean
      public WebSecurityCustomizer webSecurityCustomizer() {
          // h2-console 사용 및 resources 접근 허용 설정
          return (web) -> web.ignoring()
  //                .requestMatchers(PathRequest.toH2Console())
                  .requestMatchers(PathRequest.toStaticResources().atCommonLocations());
      }

      @Bean
      public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
          http.csrf().disable();

          // 기본 설정인 Session 방식은 사용하지 않고 JWT 방식을 사용하기 위한 설정
          http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

          http.authorizeRequests().antMatchers(HttpMethod.POST, "/api/auth/signup").permitAll()
                  .antMatchers(HttpMethod.POST, "/api/auth/login").permitAll()
                  .antMatchers(HttpMethod.GET, "/api/post", "/api/post/{postId}").permitAll()
                  .anyRequest().authenticated()
                  // JWT 인증/인가를 사용하기 위한 설정
                  .and().addFilterBefore(new JwtAuthFilter(jwtUtil), UsernamePasswordAuthenticationFilter.class);

  //        http.formLogin().loginPage("/api/auth/token-error").permitAll();
          http.cors();

          return http.build();
      }

아래는 추가된 코드이다.

  @Bean
  public CorsConfigurationSource corsConfigurationSource(){

      CorsConfiguration config = new CorsConfiguration();

      // 사전에 약속된 출처를 명시
      config.addAllowedOrigin("http://localhost:3000");
      //config.addAllowedOrigin("http://charleybucket.s3-website.ap-northeast-2.amazonaws.com");

      // 특정 헤더를 클라이언트 측에서 사용할 수 있게 지정
      // 만약 지정하지 않는다면, Authorization 헤더 내의 토큰 값을 사용할 수 없음
      config.addExposedHeader("Authorization");

      // 본 요청에 허용할 HTTP method(예비 요청에 대한 응답 헤더에 추가됨)
      config.addAllowedMethod("*");

      // 본 요청에 허용할 HTTP header(예비 요청에 대한 응답 헤더에 추가됨)
      config.addAllowedHeader("*");

      // 기본적으로 브라우저에서 인증 관련 정보들을 요청 헤더에 담지 않음
      // 이 설정을 통해서 브라우저에서 인증 관련 정보들을 요청 헤더에 담을 수 있도록 해줍니다.
      config.setAllowCredentials(true);

      // allowCredentials 를 true로 하였을 때,
      // allowedOrigin의 값이 * (즉, 모두 허용)이 설정될 수 없도록 검증합니다.
      config.validateAllowCredentials();

      // 어떤 경로에 이 설정을 적용할 지 명시합니다. (여기서는 전체 경로)
      UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
      source.registerCorsConfiguration("/**", config);

      return source;
  }

'TIL' 카테고리의 다른 글

CI/CD 자동배포  (0) 2023.03.23
Stream() 사용 방법.  (0) 2023.03.20
AWS - EC2, RDS 내 SpringBoot 프로젝트와 연결하기  (0) 2023.03.18
다양한 Exception 커스텀하는 방법.  (0) 2023.03.16
IOC와 DI란 ??  (0) 2023.03.12