React와 Spring을 연동하기 위한 프로젝트를 진행하게 되었습니다!
SpringBoot말고 Spring Legacy를 사용하자는 미션이 있었는데 통신을 할때 에러가 발생했습니다...
아무리 검색을 해서 찾아봐도 SpringBoot와 React를 연결하여 Spring Security로 cors에러를 해결하는 방법만 나와있고 Legacy 프로젝트에서 해결하는 방법은 찾기가 매우매우 힘들었습니다...!
결론부터 말하자면 굳이 Spring Security를 쓰지 않아도 됩니다!
대부분의 검색 결과에서 Spring Security를 사용했던것 처럼 처음에는 Spring에서 CORS에러는 Spring Security의 Cors를 통해 해결이 가능한 줄 알았지만 Spring에서 설정파일의 CORS옵션을 제대로 읽지 못하는 문제가 발생하여 response header를 Filter에서 request값을 이용해 설정을 해주었습니다.
React의 에러에서 힌트를 얻었는데요.
access-Control-Allow-origin header의 값이 세팅이 되지 않았다는 에러는 뜨는데 세팅 되어 있는 값은 또 잘뜨고...
모질라 문서 나오길래 바로 접속했더니
https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
가능한 Access-Control-Allow-Origin 값을 허용된 origin 집합으로 제한하는 것은 요청 헤더의 Origin를 검사하는 서버 측 코드가 필요합니다. 이를 허용된 origin 리스트와 비교하고, Origin 값이 리스트에 있으면 Access-Control-Allow-Origin 값을 Origin과 동일한 값으로 설정합니다.
라는 내용이 있더군요.
그런데 디펜던시를 이용해서 cors를 해결하려다가 같이 프로젝트를 하던 팀원과 직접 헤더값을 설정하면 되는거 아닌가 싶어서 좀더 알아보니 찾던 코드가 있었습니다!
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class SimpleCORSFilter implements Filter {
private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);
public SimpleCORSFilter() {
log.info("SimpleCORSFilter init");
}
@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", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
chain.doFilter(req, res);
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
request에서 header의 origin 값만 가지고 와서 설정을 해주면 되겠다 싶어서 바로 설정했더니 해결이 되었습니다....
라이브러리 안쓰고 직접 설정해본건 처음이라 너무 짜릿했습니다!
팀원이 알아보기로는 보통은 시큐리티는 보안쪽으로 다룬다거나 다른 용도로 많이 쓰이고 직접 헤더를 정확하게 프론트단과 맞물릴 수 있도록 설정한다고 합니다.
정확한 자원의 Origin 을 써주는 것이 중요한 것 같습니다.
req.getHeader("Origin")으로 작성하여 모든 요청을 다 허용할수 있지만 이후 배포를 할때에는 Origin 대신 localhost:3000으로 바꿔야 할것같습니다! ( 주의 할점!! 마지막에 / 붙이면 안됨!! /를 붙이면 최상위 루트라고 인식을 해서 에러가 발생합니다. )
참고로 header의 origin 은 fetch 가 시작되는 위치라고도 합니다!
https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Origin
이제 LogFilter를 만들어주고 web.xml에 연결해주면 해결이 됩니다!
//web.xml
<filter>
<filter-name>logFilter</filter-name>
<filter-class>com.kh.swith.common.filter.LogFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>logFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
'기타' 카테고리의 다른 글
hosts 파일을 이용하여 localhost 도메인 주소 설정하기 (2) | 2022.09.28 |
---|