프로젝트를 진행하던 중 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() {...}
}
보는 바와 같이, response의 Access-Control-Allow-Origin 헤더에 리소스에 대한 접근을 허용해 줄 origin을 명시해 두는 방법으로 문제를 해결했다.
프로젝트가 진행됨에 따라 프론트엔드의 서비스 도메인에서 리소스에 대한 접근이 가능하게 만들어 주어야 했고, 개발환경 역시 여전히 리소스에 대한 접근이 필요했다.
하지만, 위의 코드는 Http 응답 헤더를 추가하는 것이고, Access-Control-Allow-Origin 헤더는 하나의 값 밖에 가지지 못한다. 즉, 둘 이상의 origin을 Access-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() {...}
}
아래는 수정 이후의 변경사항이다.
CorsFilter를 생성할 때, 허용하고자 하는 origin들의 리스트를 만들어 둔다.private static HashSet<String> alloweOrigin = new HashSet<>();
@Override
public void init(FilterConfig filterConfig) ... {
//...//
alloweOrigin.add("http://localhost:3000");
alloweOrigin.add(`FE 서비스 도메인의 origin`);
//...//
}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에 대해 접근을 허용해 주어야 하는 경우에 대해 문제를 해결해 보았다.