2023. 5. 19. 15:48ㆍSpring Framework/Web on Servlet Stack
Spring Web 모듈 필터 개요
Spring Web 모듈은 서블릿 기반 애플리케이션에서 웹 요청을 처리하는 데 유용한 여러 필터를 제공합니다. 이 필터들은 폼 데이터 처리, 전달된 헤더 관리, 얕은 ETag 캐싱, CORS(교차 출처 리소스 공유) 처리를 위한 기능을 제공합니다. 각 필터의 역할에 대해 자세히 살펴보겠습니다.
Form Data 필터
기본적으로 브라우저에서는 HTTP GET
또는 POST
메서드를 통해서만 폼 데이터를 전송할 수 있습니다. 하지만 비-브라우저 클라이언트(예: REST 클라이언트)는 다른 HTTP 메서드인 PUT
, PATCH
, 또는 DELETE
를 사용하여 폼 데이터를 전송할 수 있습니다. Servlet API는 POST
요청에 대해서만 ServletRequest.getParameter*()
메서드를 통해 폼 데이터에 접근할 수 있도록 제한하고 있기 때문에, PUT
, PATCH
, 또는 DELETE
요청의 폼 데이터는 기본적으로 접근할 수 없습니다.
이를 해결하기 위해 Spring Web 모듈은 FormContentFilter를 제공합니다. 이 필터는 application/x-www-form-urlencoded
콘텐츠 유형의 PUT
, PATCH
, DELETE
요청을 가로채어 요청 본문에서 폼 데이터를 읽고, ServletRequest
를 래핑하여 ServletRequest.getParameter*()
메서드를 통해 폼 데이터를 접근할 수 있도록 합니다. 이는 POST
요청에서 폼 데이터를 처리하는 방식과 유사합니다.
사용 예:
PUT
,PATCH
,DELETE
메서드에서 폼 제출을 지원해야 할 때 FormContentFilter는 폼 필드를POST
요청과 동일하게 접근할 수 있도록 보장합니다.
Forwarded Headers 필터
여러 프록시(예: 로드 밸런서 또는 리버스 프록시)를 거치는 요청의 경우, 원본 요청의 호스트, 포트 및 스킴이 변경될 수 있습니다. 이로 인해 서버가 클라이언트 요청에 대해 링크나 리디렉션을 생성할 때 문제가 발생할 수 있습니다. 서버는 클라이언트가 본래 요청한 내용과 다른 정보로 처리할 수 있기 때문입니다.
Forwarded HTTP 헤더:
- RFC 7239는 원본 요청에 대한 정보를 전달하기 위해
Forwarded
라는 표준 헤더를 정의합니다. X-Forwarded-Host
,X-Forwarded-Port
,X-Forwarded-Proto
,X-Forwarded-Ssl
,X-Forwarded-Prefix
와 같은 표준이 아닌 헤더도 많이 사용됩니다.
주요 헤더:
- X-Forwarded-Host: 원본 호스트를 전달합니다.
- X-Forwarded-Port: 원본 포트를 전달합니다.
- X-Forwarded-Proto: 원본 프로토콜(예:
http
또는https
)을 전달합니다. - X-Forwarded-Ssl: SSL 사용 여부(
on
또는off
)를 전달합니다. - X-Forwarded-Prefix: 원본 URL 경로 접두어를 전달합니다.
ForwardedHeaderFilter:
Spring Web은 ForwardedHeaderFilter를 제공하며, 이 필터는 다음과 같은 역할을 합니다:
- 전달된 헤더에 따라 요청의
host
,port
,scheme
을 조정합니다. - 요청을 수정한 후, 해당 헤더를 제거하여 이후 처리에 영향을 미치지 않도록 합니다.
리버스 프록시를 사용할 때 ForwardedHeaderFilter는 서버가 원본 클라이언트 요청 정보와 일관되게 요청을 처리할 수 있도록 해줍니다.
보안 고려 사항:
X-Forwarded-Host
와 같은 헤더는 스푸핑될 수 있으므로, 신뢰할 수 있는 프록시만 이러한 헤더를 추가 또는 제거할 수 있도록 해야 합니다. 그렇지 않으면 악의적인 클라이언트가 헤더를 조작하여 애플리케이션을 속일 수 있습니다.removeOnly=true
로 ForwardedHeaderFilter를 구성하여 헤더를 사용하는 대신 제거만 할 수도 있습니다.
Shallow ETag 필터
ETag(엔터티 태그)는 동일한 데이터를 여러 번 전송하지 않도록 돕는 웹 캐싱 메커니즘입니다. Spring Web의 ShallowEtagHeaderFilter는 웹 응답에 대한 얕은 ETag를 생성하는 데 사용됩니다.
작동 방식:
- 필터는 응답 내용을 캡처하고 MD5 해시를 계산한 후, 이를 ETag 헤더로 설정합니다.
- 이후 클라이언트가 동일한 ETag 값을 포함한
If-None-Match
헤더를 제공하면, 서버는304 Not Modified
응답을 반환하여 대역폭을 절약할 수 있습니다.
얕은 ETag와 깊은 ETag:
- "얕은" ETag는 요청 세부 사항을 고려하지 않고 응답 내용만을 기반으로 ETag를 생성하는 것을 의미합니다. "깊은" ETag는 더 복잡한 체크를 포함할 수 있습니다.
- 이 필터는 RFC 7232에서 정의된 대로 "약한" ETag(예:
W/"etag-value"
)를 작성하는 기능을 지원합니다.
제한 사항:
- 이 필터는 CPU 자원을 절약하지는 않습니다. 응답이 완전히 생성된 후에야 ETag를 계산할 수 있기 때문입니다.
CORS (교차 출처 리소스 공유)
CORS는 웹 서버의 리소스를 다른 도메인에서 요청할 수 있도록 하는 메커니즘으로, 현대 웹 애플리케이션에서 필수적입니다. Spring은 다음과 같은 방법으로 CORS에 대한 세밀한 지원을 제공합니다:
- 어노테이션: Spring MVC 컨트롤러에서 직접 CORS를 구성할 수 있습니다.
- CorsFilter: CORS 정책을 처리하는 필터로, Spring Security의 필터 체인보다 앞서 배치되어야 합니다.
이를 통해 어떤 출처(origin)가 리소스에 접근할 수 있는지, 어떤 HTTP 메서드와 헤더가 허용되는지, 쿠키와 같은 자격 증명이 요청과 함께 전송될 수 있는지를 정의할 수 있습니다.
Spring Security 통합:
Spring Security를 사용하는 경우, CorsFilter를 사용하여 CORS를 관리하는 것이 좋습니다. Spring Security도 자체적으로 CORS 처리를 구현하고 있기 때문입니다.
Dispatcher Types 및 비동기 요청
ForwardedHeaderFilter와 ShallowEtagHeaderFilter와 같은 필터들이 비동기 요청을 올바르게 처리하려면 DispatcherType.ASYNC
와 함께 등록해야 합니다. 이렇게 하면 필터가 비동기 디스패치를 사용하는 요청을 처리할 수 있습니다. 비동기 요청 외에도 에러 처리를 위해 필터들이 DispatcherType.ERROR
와 함께 등록되어야 에러 디스패치 시나리오도 처리할 수 있습니다.
AbstractAnnotationConfigDispatcherServletInitializer
를 사용하는 경우, 모든 필터는 자동으로 모든 디스패처 타입(REQUEST
, ASYNC
, ERROR
등)으로 등록됩니다. 하지만 필터를 수동으로 등록하는 경우(Spring Boot에서 FilterRegistrationBean
을 사용하는 경우), DispatcherType.ASYNC
와 DispatcherType.ERROR
를 명시적으로 포함해야 합니다.
요약
- FormContentFilter:
PUT
,PATCH
,DELETE
요청에서 폼 데이터를POST
요청과 동일하게 접근할 수 있게 합니다. - ForwardedHeaderFilter:
Forwarded
및X-Forwarded-*
와 같은 헤더를 처리하여 올바른 호스트, 포트, 스킴 정보를 유지합니다. - ShallowEtagHeaderFilter: 얕은 ETag 기반 캐싱을 제공하여 네트워크 효율성을 향상시킵니다.
- CorsFilter: 교차 출처 요청에 대한 세밀한 CORS 구성을 가능하게 합니다.
이 필터들은 폼 데이터 제출, 캐싱, 리버스 프록시 통합, CORS 처리 등의 다양한 시나리오를 다룰 수 있도록 하여 웹 애플리케이션의 유연성과 성능을 유지할 수 있게 해줍니다.
참고 : [https://docs.spring.io/spring-framework/reference/web/webmvc/filters.html]
'Spring Framework > Web on Servlet Stack' 카테고리의 다른 글
@RequestHeader (0) | 2024.10.09 |
---|---|
Annotated Controllers[1] (1) | 2024.10.06 |
Dispatcher Servlet (0) | 2023.05.02 |
WebDataBinder (0) | 2023.05.01 |
Servlet (0) | 2023.04.17 |