#java #spring #spring-boot #tomcat #spring-hateoas
Вопрос:
Я недавно обновил spring boot с 1.x до 2.y и столкнулся с этой проблемой, когда ссылки hateoas были сгенерированы со http
схемой вместо https
.
Позже я обнаружил, что в spring boot 2.2 обязательно использовать следующее свойство
server.forward-headers-strategy=NATIVE
который может иметь одно из NATIVE
или FRAMEWORK
или NONE
.
NONE
свойство довольно прямолинейно, и оно полностью отключает использование прямых заголовков.
Но четкой документации по NATIVE
vs нет FRAMEWORK
. Я видел во многих местах, где упоминается, что NATIVE
в большинстве случаев работает лучше всего. Но нет никакого объяснения того, что именно происходит за кулисами, когда мы используем эти свойства.
Документация здесь не дает мне достаточной информации для выбора между собственным/фреймворком. Все, что в нем говорится, — это кто обрабатывает пересылаемые заголовки для соответствующих значений. Контейнер сервлета? или пружинный каркас? но это возвращает нас к квадрату 1. Должен ли я позволить контейнеру справиться с этим? или рамки? когда я должен предпочесть одно другому?
Я использую веб-приложение REST с внешним котом и Hateoas
для создания ссылок.
Как мне решить, использовать NATIVE
или FRAMEWORK
нет собственность? Когда следует предпочесть одно другому и почему?
Моя версия для прыжков: 2.4.6
Ссылки, которые я уже пробовал:
- https://github.com/spring-projects/spring-boot/issues/18667
- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.2-Release-Notes#deprecations-in-spring-boot-22
- https://docs.spring.io/spring-framework/docs/5.1.3.RELEASE/spring-framework-reference/web.html#filters-forwarded-headers
- https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#filters-forwarded-headers
Редактировать:
Я попробовал оба решения и framework
работает для меня, но не native
во внешней среде tomcat. Я создал новое веб-приложение spring boot со встроенным tomcat, и то native
и framework
другое работает.
Ответ №1:
рамки
FRAMEWORK
использует поддержку Spring для обработки пересылаемых заголовков. Например, Spring Boot auto создает ForwardedHeaderFilter
компонент для Spring MVC when server.forward-headers-strategy=framework
.
@Bean
@ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class)
@ConditionalOnProperty(value = "server.forward-headers-strategy", havingValue = "framework")
public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
FilterRegistrationBean<ForwardedHeaderFilter> registration = new FilterRegistrationBean<>(filter);
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR);
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}
ForwardedHeaderFilter
обрабатывает нестандартные заголовки X-Forwarded-Host
, X-Forwarded-Port
, X-Forwarded-Proto
, X-Forwarded-Ssl
, и X-Forwarded-Prefix
.
родной
NATIVE
использует встроенную поддержку базового контейнера для пересылаемых заголовков. Базовый контейнер означает tomcat, причал, нетти и т. Д. Например, встроенный Tomcat, который автоматически настраивается с помощью Spring Boot, обрабатывает нестандартные заголовки X-Forwarded-Host
, X-Forwarded-Port
, X-Forwarded-Proto
, X-Forwarded-Ssl
, но нет X-Forwarded-Prefix
.
X-Переадресованный-Префикс
Например, включен шлюз API localhost:8080
и включена служба api sga-booking
localhost:20000
. Маршрут шлюза API /sga-booking
перенаправляется в службу api sga-booking
. Запрос на localhost:8080/sga-booking
содержит заголовки:
forwarded = proto=http;host="localhost:8080";for="0:0:0:0:0:0:0:1%0:46706"
x-forwarded-for = 0:0:0:0:0:0:0:1%0
x-forwarded-proto = http
x-forwarded-prefix = /sga-booking
x-forwarded-port = 8080
x-forwarded-host = localhost:8080
host = 192.168.31.200:20000
При ForwardedHeaderFilter
обработке пересылаемых заголовков, включая X-Forwarded-Prefix
сгенерированные ссылки localhost:8080/sga-booking
,начинается с. Если X-Forwarded-Prefix
не обрабатывается, сгенерированные ссылки начинаются с localhost:8080
.
Встроенный Tomcat автоматически настраивается при загрузке Spring
С помощью свойства server.forward-headers-strategy=native
метод org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer#customizeRemoteIpValve
настраивает a RemoteIpValve
со свойствами server.tomcat.remoteip
( org.springframework.boot.autoconfigure.web.ServerProperties.Tomcat.Remoteip
) для обработки пересылаемых заголовков. Обратите внимание, что X-Forwarded-Prefix
это не обрабатывается.
private void customizeRemoteIpValve(ConfigurableTomcatWebServerFactory factory) {
Remoteip remoteIpProperties = this.serverProperties.getTomcat().getRemoteip();
String protocolHeader = remoteIpProperties.getProtocolHeader();
String remoteIpHeader = remoteIpProperties.getRemoteIpHeader();
if (StringUtils.hasText(protocolHeader) || StringUtils.hasText(remoteIpHeader)
|| getOrDeduceUseForwardHeaders()) {
RemoteIpValve valve = new RemoteIpValve();
valve.setProtocolHeader(StringUtils.hasLength(protocolHeader) ? protocolHeader : "X-Forwarded-Proto");
if (StringUtils.hasLength(remoteIpHeader)) {
valve.setRemoteIpHeader(remoteIpHeader);
}
valve.setInternalProxies(remoteIpProperties.getInternalProxies());
try {
// X-Forwarded-Host by default
valve.setHostHeader(remoteIpProperties.getHostHeader());
}
catch (NoSuchMethodError ex) {
// Avoid failure with war deployments to Tomcat 8.5 before 8.5.44 and
// Tomcat 9 before 9.0.23
}
// X-Forwarded-Port by default
valve.setPortHeader(remoteIpProperties.getPortHeader());
valve.setProtocolHeaderHttpsValue(remoteIpProperties.getProtocolHeaderHttpsValue());
factory.addEngineValves(valve);
}
}
Внешний Кот
// Извините, что я не играл в ванильного Кота в течение многих лет после окончания школы. Ниже информация о Tomcat может быть неверной.
Чтобы внешний Tomcat обрабатывал перенаправленные заголовки, такие как настройки Spring Boot, я думаю, что A RemoteIpValve
должен быть настроен с помощью add
<Context>
...
<Valve className="org.apache.catalina.valves.RemoteIpValve"
hostHeader="X-Forwarded-Host"
portHeader="X-Forwarded-Port"
...
/>
...
</Context>
к Коту server.xml
? или context.xml
?
Здесь вы найдете все атрибуты удаленного ip-клапана. Обратите внимание, что ни с одним атрибутом это не связано X-Forwarded-Prefix
.
Фильтр Tomcat RemoteIpFilter
может иметь аналогичную функцию. Я не знаю, в чем их разница.
Ссылка
Комментарии:
1. Что именно это означает для обработки пересылаемых заголовков? Чем контейнер сервлета, обрабатывающий его, отличается от фреймворка, обрабатывающего его?
2. Ответ @ArunGowda дополнен примером, объясняющим разницу.
3. Имеет ли
native
framework
значение / во внешнем коте? Потому что, как я уже упоминал в своей правке, они ведут себя по-другому. Во встроенном tomcat оба значения работают с Hateoas, в то время как во внешнем tomcatframework
работает только и неnative
работает .