프로젝트를 진행하던 중 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
에 대해 접근을 허용해 주어야 하는 경우에 대해 문제를 해결해 보았다.