Spring server.прямые заголовки-стратегия РОДНОЙ vs ФРЕЙМВОРК

#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

Ссылки, которые я уже пробовал:

Редактировать:

Я попробовал оба решения и 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, в то время как во внешнем tomcat framework работает только и не native работает .