CORS - 두 개 이상의 Origin 허용하기

짱수·2023년 4월 5일
0

짱수의 개발일지

목록 보기
2/2

📝 서론

프로젝트를 진행하던 중 CORS 관련 문제를 만났다.
이 때, 문제를 해결하기 위해 Filter 인터페이스를 구현하여 문제를 해결하였다.
그리고, 시간이 지나 프론트에서 또 하나의 Origin에서 CORS 문제를 해결해 달라고 요청하였다.
천천히 문제를 해결해 보자.

🛠️ 문제해결 과정

기존 나의 코드

아래는 기존의 나의 CorsFilter 코드 일부이다.

import jakarta.servlet.Filter;
...
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class CorsFilter implements Filter {
	@Override
	public void init(FilterConfig filterConfig) ...{...}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, 
    	FilterChain chain) ...{

		log.info("launch CorsFilter.doFilter");
		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-Allow-Headers", 
        	"Origin, X-Requested-With, Content-Type, Accept, Authorization");

		//...//
	}

	@Override
	public void destroy() {...}
}

보는 바와 같이, responseAccess-Control-Allow-Origin 헤더에 리소스에 대한 접근을 허용해 줄 origin을 명시해 두는 방법으로 문제를 해결했다.

문제점

프로젝트가 진행됨에 따라 프론트엔드의 서비스 도메인에서 리소스에 대한 접근이 가능하게 만들어 주어야 했고, 개발환경 역시 여전히 리소스에 대한 접근이 필요했다.
하지만, 위의 코드는 Http 응답 헤더를 추가하는 것이고, Access-Control-Allow-Origin 헤더는 하나의 값 밖에 가지지 못한다. 즉, 둘 이상의 originAccess-Control-Allow-Origin 헤더의 값으로 설정해 줄 순 없었다.

해결 이후의 소스코드

아래는 해결 이후의 CorsFilter 코드 일부이다.

import jakarta.servlet.Filter;
...
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class CorsFilter implements Filter {
	private static HashSet<String> alloweOrigin = new HashSet<>();

	@Override
	public void init(FilterConfig filterConfig) ...{
		Filter.super.init(filterConfig);

		// 1)
		alloweOrigin.add("http://localhost:3000");
		alloweOrigin.add(`FE 서비스 도메인의 origin`);

	}

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

		// 2)
		String origin = request.getHeader(HttpConst.ORIGIN);
		if(alloweOrigin.contains(origin) == false)
			return;
		response.setHeader("Access-Control-Allow-Origin", origin);
		response.setHeader("Access-Control-Allow-Credentials", "true");
		response.setHeader("Access-Control-Allow-Methods", "*");
		response.setHeader("Access-Control-Allow-Headers", 
        	"Origin, X-Requested-With, Content-Type, Accept, Authorization");
        
		//...//
		}

	@Override
	public void destroy() {...}
}

변경사항

아래는 수정 이후의 변경사항이다.

  1. CorsFilter를 생성할 때, 허용하고자 하는 origin들의 리스트를 만들어 둔다.
    private static HashSet<String> alloweOrigin = new HashSet<>();
        @Override
        public void init(FilterConfig filterConfig) ... {
            //...//
            alloweOrigin.add("http://localhost:3000");
            alloweOrigin.add(`FE 서비스 도메인의 origin`);
            //...//
        }
  2. 주어진 요청의 origin을 확인 후, 허용 리스트에 포함된 origin이라면 주어진 요청의 origin을 그대로 Access-Control-Allow-Origin 헤더의 값으로 사용한다.
    @Override
    public void doFilter(...){
        // ... //
    	String origin = request.getHeader(HttpConst.ORIGIN);
    	if(alloweOrigin.contains(origin) == false)
    		return;
    	response.setHeader("Access-Control-Allow-Origin", origin);
    	//...//
    	}

✒️정리

CORS를 해결해 주기 위해 다양한 방법이 존재하며, 이번 프로젝트에서는 필터를 사용했다.
그 과정에서 두가지 이상의 origin에 대해 접근을 허용해 주어야 하는 경우에 대해 문제를 해결해 보았다.

profile
Zangsu

0개의 댓글