inblog logo
|
sxias
    REST API

    [REST API] 21. CORS

    문정준's avatar
    문정준
    May 15, 2025
    [REST API] 21. CORS
    Contents
    1. Origin / Remote Address2. CSRF Defence3. CORS (Cross Origin Resource Sharing)4. 적용
     

    1. Origin / Remote Address

    • 클라이언트가 특정 서버에 request를 요청할 때에, 서버는 클라이언트의 IP 주소 (Host 주소, Remote Address)도 수집해야 하지만 제일 먼저 요청이 어디서 들어 왔는지 확인해야 함
    • 서버의 도메인 주소가 naver.com인데, 다른 사이트에서 naver.com에게 요청을 보내면 비정상적인 접근으로 판단하여 접근을 차단하기 때문
      • 요청을 보낸 근원지를 Origin이라고 하고, 이는 클라이언트의 IP 주소와 다름
    • 서버는 실제로 Remote Address 외에도 Origin, Referer (이전 주소), User-Agent, CSRF Token 등 요청이 안전하다는 증거를 입증 가능한 정보들을 받아야 함
      • Origin, Referer, User-Agent 등은 공격자가 임의로 조작이 가능하기 때문에, 추가로 필요한 검증용 토큰이 바로 CSRF (Cross-Site Request Forgery) Token
    notion image

    Referer

    🌐HTTP referer 란?
    HTTP Referer referer는 http 헤더중 하나이다. HTTP 프로토콜에는 referer 라는 헤더값이 있는데, 브라우저가 서버로 이 헤더값을 설정해서 보내게 된다. 그리고 서버는 referer를 참조함으로써 현재 표시 하는 웹페이지가 어떤 웹페이지에서 요청되었는지 알수 있으며, 어떤 웹사이트나 웹서버에서 방문자가 왔는지를 파악할수 있는 기능을 referer 를 통해 할수 있다. 예를들어, http://www.test.com/1.html 이라는 웹페이지에 있는 링크를 클릭하여 http://www.power.com/2.html 으로 이동했을 때 referer는 http://www.test.com/1.html 이 된다. 간단하게 말하자면, 헤더에 담겨 있는 현재 페이지에 요청한 이전 페이지의 u..
    🌐HTTP referer 란?
    https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-HTTP-referer-%EB%9E%80
    🌐HTTP referer 란?

    2. CSRF Defence

    • CSRF는 사용자의 인증 상태를 악용하여, 사용자가 의도하지 않은 요청을 보내도록 유도하는 공격
    • 피싱 사이트 등을 통해 인증 정보를 이용하여 공격하기 때문에 사용자와 서버 양 측에서는 이 요청이 올바른 요청인지, 악의를 가진 공격성 요청인지 알 수 없음
      • 이를 검증하기 위해 토큰(CSRF Token)을 사용
    • 토큰을 사용할 시 정상적인 서버에서는 세션을 통해 토큰을 지급하고 검증
      • 공격자는 토큰의 값을 알 수 없고, 위조할 수 없음
    notion image
     

    3. CORS (Cross Origin Resource Sharing)

    • CSRF 방어의 정책 때문에, HTTP 프로토콜은 같은 Origin이 아닌 곳의 요청을 기본적으로 전부 차단
    • 신뢰할 수 있는 특정 Origin의 요청을 열어주는 것이 바로 CORS (Cross Origin Resource Sharing)
    notion image
    • Origin을 확인하기 위해서 클라이언트는 JS를 통한 요청 시 2번의 요청을 전송
      • 맨 먼저 전송하는 요청을 Preflight라고 함
      • Preflight에서 내가 전송할 요청의 정보를 알려주고, 서버에서 신뢰할 수 있어 요청을 허용하는 응답이 오면 본 요청을 다시 전송
      • Preflight가 거절되면 브라우저에서 에러 출력
    notion image
    notion image
     

    4. 적용

    • 실제 운영할 Blog에 적용하기 위해 Filter를 사용
     
    • CorsFilter
      • Access-Control-Allow-Origin : 서버 측에서 접근을 허용하는 Origin 명시
      • Access-Control-Expose-Headers : 서버 측에서 응답에 남길 수 있는 Headers 명시
      • Access-Control-Allow-Methods : 서버 측에서 허용할 수 있는 Request Methods
        • Preflight는 Options라는 Method를 사용하므로 필수로 포함해야 함
      • Access-Control-Max-Age : 서버 측에서 CORS를 허용할 수 있는 시간 (초)
      • Access-Control-Allow-Headers : 서버 측에서 요청 받을 수 있는 헤더
        • Access-Control-Expose-Headers와 다름
      • Access-Control-Allow-Credentials : 서버에서 쿠키에 세션 값을 담는 것을 허용할 지에 대한 여부
    @Slf4j public class CorsFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; String origin = request.getHeader("Origin"); log.debug("Origin : " + origin); response.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:5500"); // response.setHeader("Access-Control-Expose-Headers", "Authorization"); // 응답 해줄 수 있는 헤더 response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, DELETE, OPTIONS"); // OPTIONS : Preflight response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Origin, X-Key, Content-Type, Accept, Authorization"); // 요청 받을 수 있는 헤더 // X-~~~ : Customized Header response.setHeader("Access-Control-Allow-Credentials", "true"); // 쿠키 세션 값 허용 // Preflight 요청을 허용하고 바로 응답하는 코드 if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); } else { chain.doFilter(req, res); } } }
     
    • FilterConfig
    @Bean public FilterRegistrationBean<CorsFilter> corsFilter() { FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new CorsFilter()); registrationBean.addUrlPatterns("/*"); // 모든 요청에 적용 registrationBean.setOrder(1); // 필터 순서 설정 return registrationBean; }
     
     

    Result

    • Cursor의 Live Server (127.0.0.1:5500)를 이용하여 Preflight가 승인되는 지 확인
    Preflight 허용
    Preflight 허용
    Preflight Response Headers
    Preflight Response Headers
    Share article
    Contents
    1. Origin / Remote Address2. CSRF Defence3. CORS (Cross Origin Resource Sharing)4. 적용

    Sxias ㆍ a32176740@gmail.com

    RSS·Powered by Inblog