spring-web
모듈은 몇 가지 유용한 필터를 제공합니다:
브라우저는 HTTP GET 또는 HTTP POST를 통해서만 양식 데이터를 제출할 수 있지만 브라우저가 아닌 클라이언트는 HTTP PUT, PATCH 및 DELETE를 사용할 수도 있습니다. Servlet API에는 HTTP POST에 대해서만 양식 필드 액세스를 지원하기 위한 ServletRequest.getParameter*()
메소드가 필요합니다.
spring-web
모듈은 FormContentFilter
를 제공하여 application/x-www-form-urlencoded
콘텐츠 유형으로 HTTP PUT, PATCH 및 DELETE 요청을 가로채고, 요청 본문에서 양식 데이터를 읽고, ServletRequest
를 래핑하여 ServletRequest.getParameter*()
메소드 계열을 통해 사용할 수 있는 양식 데이터입니다.
요청이 로드 밸런서와 같은 프록시를 통과함에 따라 호스트, 포트 및 체계가 변경될 수 있으며 이로 인해 클라이언트 관점에서 올바른 호스트, 포트 및 체계를 가리키는 링크를 생성하는 것이 어려워집니다.
RFC 7239는 프록시가 원래 요청에 대한 정보를 제공하는 데 사용할 수 있는 Forwarded
HTTP 헤더를 정의합니다.
X-Forwarded-Host
, X-Forwarded-Port
, X-Forwarded-Proto
, X-Forwarded-Ssl
및 X-Forwarded-Prefix
를 포함한 다른 비표준 헤더도 있습니다.
표준은 아니지만 X-Forwarded-Host: <host>
는 원래 호스트를 다운스트림 서버와 통신하는 데 사용되는 사실상의 표준 헤더입니다. 예를 들어, example.com/resource
요청이 요청을 localhost:8080/resource
로 전달하는 프록시로 전송되면 X-Forwarded-Host: example.com
헤더가 서버에 전송될 수 있습니다. 원래 호스트는 example.com
이었습니다.
표준은 아니지만 X-Forwarded-Port: <port>
는 원래 포트를 다운스트림 서버에 전달하는 데 사용되는 사실상의 표준 헤더입니다. 예를 들어, example.com/resource
요청이 요청을 localhost:8080/resource
로 전달하는 프록시로 전송되면 X-Forwarded-Port: 443
헤더가 전송되어 원래 443
포트가 서버에 있음을 알릴 수 있습니다.
표준은 아니지만 X-Forwarded-Proto: (https|http)
는 원래 프로토콜(예: https / https)을 다운스트림 서버에 전달하는 데 사용되는 사실상의 표준 헤더입니다. 예를 들어, example.com/resource
의 요청이 요청을 localhost:8080/resource
로 전달하는 프록시로 전송되면 X-Forwarded-Proto: https
헤더가 전송되어 원래 https
프로토콜이 서버에 있음을 알릴 수 있습니다.
표준은 아니지만 X-Forwarded-Ssl: (on|off)
는 원래 프로토콜(예: https / https)을 다운스트림 서버에 전달하는 데 사용되는 사실상의 표준 헤더입니다. 예를 들어, example.com/resource
요청이 요청을 localhost:8080/resource
로 전달하는 프록시로 전송되면 X-Forwarded-Ssl: on
헤더가 원래 프로토콜이 https
였음을 서버에 알립니다.
표준은 아니지만 X-Forwarded-Prefix: <prefix>
는 원래 URL 경로 접두어를 다운스트림 서버에 전달하는 데 사용되는 사실상의 표준 헤더입니다.
X-Forwarded-Prefix
의 사용은 배포 시나리오에 따라 다를 수 있으며 대상 서버의 경로 접두사를 대체, 제거 또는 앞에 추가할 수 있도록 유연해야 합니다.
Scenario 1: Override path prefix
https://example.com/api/{path} -> http://localhost:8080/app1/{path}
접두사는 캡처 그룹 {path}
앞의 경로 시작입니다. 프록시의 경우 접두사는 /api
이고 서버의 경우 접두사는 /app1
입니다. 이 경우 프록시는 X-Forwarded-Prefix: /api
를 보내 원래 접두사 /api
가 서버 접두사 /app1
을 재정의하도록 할 수 있습니다.
Scenario 2: Remove path prefix
때때로 응용 프로그램에서 접두사를 제거하려고 할 수도 있습니다. 예를 들어 다음 프록시-서버 매핑을 고려해보세요.
https://app1.example.com/{path} -> http://localhost:8080/app1/{path}
https://app2.example.com/{path} -> http://localhost:8080/app2/{path}
프록시에는 접두사가 없지만 app1
및 app2
애플리케이션에는 각각 경로 접두사 /app1
및 /app2
가 있습니다. 프록시는 X-Forwarded-Prefix:
를 전송하여 빈 접두사가 서버 접두사 /app1
및 /app2
를 재정의하도록 할 수 있습니다.
[Note]
이 배포 시나리오의 일반적인 경우는 프로덕션 응용 프로그램 서버별로 라이선스를 지불하는 것이며, 비용을 줄이기 위해 서버당 여러 응용 프로그램을 배포하는 것이 좋습니다. 또 다른 이유는 서버 실행에 필요한 리소스를 공유하기 위해 동일한 서버에서 더 많은 응용 프로그램을 실행하는 것입니다.이러한 시나리오에서는 동일한 서버에 여러 애플리케이션이 있으므로 애플리케이션에는 비어 있지 않은 컨텍스트 루트가 필요합니다. 그러나 이는 애플리케이션이 다음과 같은 이점을 제공하는 다른 하위 도메인을 사용할 수 있는 공개 API의 URL 경로에 표시되어서는 안 됩니다.
보안이 추가되었습니다. 동일 원산지 정책
애플리케이션의 독립적인 확장(다른 도메인은 다른 IP 주소를 가리킴)
Scenario 3: Insert path prefix
다른 경우에는 접두사를 추가해야 할 수도 있습니다. 예를 들어 다음 프록시-서버 매핑을 고려해보세요.
https://example.com/api/app1/{path} -> http://localhost:8080/app1/{path}
이 경우 프록시의 접두사는 /api/app1
이고 서버의 접두사는 /app1
입니다. 프록시는 X-Forwarded-Prefix: /api/app1
을 보내 원래 접두사 /api/app1
이 서버 접두사 /app1
을 재정의하도록 할 수 있습니다.
ForwardedHeaderFilter
는 a) Forwarded
헤더를 기반으로 호스트, 포트 및 구성표를 변경하고 b) 추가 영향을 제거하기 위해 해당 헤더를 제거하기 위해 요청을 수정하는 서블릿 필터입니다. 필터는 요청 래핑에 의존하므로 원래 요청이 아닌 수정된 요청에 작동해야 하는 RequestContextFilter
와 같은 다른 필터보다 먼저 주문되어야 합니다.
헤더가 의도한 대로 프록시에 의해 추가되었는지 아니면 악의적인 클라이언트에 의해 추가되었는지 애플리케이션이 알 수 없으므로 전달된 헤더에 대한 보안 고려 사항이 있습니다. 이것이 바로 외부에서 들어오는 신뢰할 수 없는 Forwarded
헤더를 제거하도록 신뢰 경계의 프록시를 구성해야 하는 이유입니다. 또한 removeOnly=true
로 ForwardedHeaderFilter
를 구성할 수도 있습니다. 이 경우 헤더는 제거되지만 사용되지 않습니다.
비동기 요청 및 오류 디스패치를 지원하려면 이 필터를 DispatcherType.ASYNC
및 DispatcherType.ERROR
와 매핑해야 합니다. Spring Framework의 AbstractAnnotationConfigDispatcherServletInitializer
(서블릿 구성 참조)를 사용하는 경우 모든 필터는 모든 디스패치 유형에 대해 자동으로 등록됩니다. 그러나 web.xml
을 통해 또는 Spring Boot에서 FilterRegistrationBean
을 통해 필터를 등록하는 경우 DispatcherType.REQUEST
외에 DispatcherType.ASYNC
및 DispatcherType.ERROR
를 포함해야 합니다.
ShallowEtagHeaderFilter
필터는 응답에 기록된 콘텐츠를 캐시하고 여기에서 MD5 해시를 계산하여 "얕은" ETag를 생성합니다. 다음에 클라이언트가 보낼 때 동일한 작업을 수행하지만 계산된 값을 If-None-Match
요청 헤더와 비교하여 두 값이 동일하면 304(NOT_MODIFIED)를 반환합니다.
이 전략은 각 요청에 대해 전체 응답을 계산해야 하므로 네트워크 대역폭은 절약하지만 CPU는 절약하지 않습니다. 상태 변경 HTTP 메서드와 If-Match
및 If-Unmodified-Since
와 같은 기타 HTTP 조건부 요청 헤더는 이 필터의 범위를 벗어납니다. 컨트롤러 수준의 다른 전략은 계산을 방지하고 HTTP 조건부 요청을 더 광범위하게 지원할 수 있습니다. HTTP 캐싱을 참조하세요.
이 필터에는 W/"02a2d595e6ed9a0b24f027f2b63b134d6"
(RFC 7232 섹션 2.3에 정의됨)과 유사한 약한 ETag를 쓰도록 필터를 구성하는 writeWeakETag
매개변수가 있습니다.
비동기 요청을 지원하려면 이 필터를 DispatcherType.ASYNC
와 매핑하여 필터가 마지막 비동기 디스패치 끝까지 ETag를 지연하고 성공적으로 생성할 수 있도록 해야 합니다. Spring Framework의 AbstractAnnotationConfigDispatcherServletInitializer
(서블릿 구성 참조)를 사용하는 경우 모든 필터는 모든 디스패치 유형에 대해 자동으로 등록됩니다. 그러나 web.xml
을 통해 또는 FilterRegistrationBean
을 통해 Spring Boot에 필터를 등록하는 경우 DispatcherType.ASYNC
를 포함해야 합니다.
Spring MVC는 컨트롤러의 주석을 통해 CORS 구성에 대한 세부적인 지원을 제공합니다. 그러나 Spring Security와 함께 사용할 경우 Spring Security의 필터 체인보다 먼저 주문해야 하는 내장 CorsFilter
를 사용하는 것이 좋습니다.