Projects/Team project - 스택오버플로우 클론코딩

CORS 문제 해결

마손리 2023. 6. 21. 09:37

문제 발생

프로젝트 진행 중 프론트엔드 분들을 위한 Mock-up data API를 만들어 EC2를 활용해 배포하여 제공하게 되었는데 이때 Cors 문제가 발생하게 되었다.

 

스프링 시큐리티를 사용하지 않으므로 간단하게 컨트롤러에 @CrossOrigin 에너테이션으로 해결할 수 있을줄 알았지만 계속해서 http status 415 에러가 난다는 보고를 받았다. 

 

 

문제 해결

이를 해결하기 위해 Cors filter를 직접 작성해 주기로 했다.

package com.stub_data_server.cors;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter { // javax.servlet의 Filter 구현
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        response.setHeader("Access-Control-Allow-Origin", "http://localhost:3000"); //"*" 와일드 카드 사용 불가
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods","*");
        response.setHeader("Access-Control-Max-Age", "1000000");
        response.setHeader("Access-Control-Allow-Headers",
                "Origin, X-Requested-With, Content-Type, Accept, Authorization");
                
	// 클라이언트에서 response header의 특정 필드에 접근하기 위해서 
    // "Access-Control-Expose-Headers"를 설정해 주어야 한다.
        response.setHeader("Access-Control-Expose-Headers", "authorization, refresh");

        response.setHeader("authorization", "bearer qnwjdnqwjkndjkqnwkjdnwqkjndjkqnwjdknqjwdvnmjwqnjvw");
        response.setHeader("refresh", "kqwdkjbqkjwbndjkqnvjqennoqenvqnqnmwkmdqkmwqldkml");

        if("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        }else {
            chain.doFilter(req, res);
        }
    }

    @Override
    public void destroy() {

    }
}

 

 

Spring Security

스프링 시큐리티를 사용한다면 CorsConfiguration을 사용하여 커스텀 해준다.

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        
        configuration.setAllowedOrigins(
                Arrays.asList(
                        "http://localhost:3000",
                        "http://synergyoverflow.s3-website.ap-northeast-2.amazonaws.com"
                )
        );
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PATCH", "DELETE"));
        configuration.setAllowCredentials(true);
        configuration.setMaxAge(1000L);
        configuration.setAllowedHeaders(Arrays.asList("Origin", "X-Requested-With", "Content-Type", "Accept", "Authorization"));
        configuration.setExposedHeaders(Arrays.asList("authorization", "refresh"));

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

 

유의 사항

  1. Filter 인터페이스가 여러개이기 때문에 반드시 javax.servlet의 Filter를 구현해준다.
  2. "Access-Controll-Allow-Origin" 설정에서 주소에 와일드카드"*" 사용시 계속해서 Cors 에러가 발생할 수있다. 이경우 특정 Url을 명시해 준다.
  3. Token과 같이 클라이언트에서 response header에 접근해야 하는경우 "Access-Control-Expose-Headers"를 이용하여 해당 필드에 접근이 가능하도록 노출시켜주어야한다.