Как я могу получить spring безопасность для работы за балансировщиком нагрузки по нескольким доменам?

Мы перемещаем старое приложение java/ spring в AWS, поэтому оно находится за балансировкой нагрузки приложений AWS. Tomcat работает непосредственно за балансировщиками нагрузки на порту 8080, и мы используем HTTP между балансировщиком нагрузки и tomcat.

Проблема заключается в том, что этот модуль безопасности spring не распознает, что соединение безопасно.

Я могу решить эту проблему, настроив Connection:

<Connector port="8080"
           protocol="HTTP/1.1"
           connectionTimeout="20000"
           proxyName="single-host.example.com"
           secure="true"
           scheme="https"
           redirectPort="443"
           proxyPort="443" />

Что работает для одного имени хоста. Однако мне нужно это, чтобы работать с несколькими именами хостов.

Я пробовал пропустить прокси и добавил:

server.tomcat.remote_ip_header=X-Forwarded-For
server.tomcat.protocol_header=X-Forwarded-Proto

Но это, похоже, не имеет никакого значения.

Есть ли способ поддерживать несколько имен хостов в этом сценарии?

Ответ 1

AWS LoadBalancer отправляет заголовок X-Forwarded-Proto при запросе прокси.

В Tomcat настройте RemoteIpValve, чтобы request.secure и другой переменной запроса, интерпретируемой из этих заголовков.

<Valve className="org.apache.catalina.valves.RemoteIpValve"/>

Вы также должны опустить настройку proxyName на Connector conifiguration, так как она должна автоматически поступать с клапана.

Ответ 2

У меня есть процедура решения. Поэтому я дал 2 предложения. Первое - пошаговое графическое представление, чтобы решить вашу проблему. Если нет, перейдите ко второму.

Во второй используется X-Forwarded-Proto и соответствующая конфигурация для решения проблемы. Надеюсь, это поможет вам.

Предложение # 1:

Облачная среда Amazon с поддержкой поддержки баланса нагрузки довольно проста. Пошаговое руководство приведено здесь: Эластичная балансировка нагрузки (ELB) с веб-приложением Java + Tomcat + Session Stickiness

Предложение # 2:

phillipuniverse дал решение.

Конфигурирование следующего клапана в Tomcat будет правильно выполнять функцию request.isSecure() с заголовком X-Forwarded-Proto:

<Valve className="org.apache.catalina.valves.RemoteIpValve" protocolHeader="X-Forwarded-Proto" />

Это можно добавить к Tomcat server.xml под элементом <Host>.


И, конечно же, после всего этого существует очень, очень простое решение, которое исправляет эту проблему с самого начала. Все, что действительно должно было произойти, состояло в том, чтобы изменить фильтры прото-каналов:

if ("https".equals(invocation.getHttpRequest().getHeader("X-Forwarded-Proto"))) {
    getEntryPoint().commence(invocation.getRequest(), invocation.getResponse());
}

до

if (invocation.getHttpRequest().isSecure() || 
        "https".equals(invocation.getHttpRequest().getHeader("X-Forwarded-Proto"))) {
    getEntryPoint().commence(invocation.getRequest(), invocation.getResponse());
}

Конечная конфигурация здесь должна быть следующей:

<bean class="org.broadleafcommerce.common.security.channel.ProtoChannelBeanPostProcessor">
    <property name="channelProcessorOverrides">
      <list>
        <bean class="org.broadleafcommerce.common.security.channel.ProtoInsecureChannelProcessor" />
        <bean class="org.broadleafcommerce.common.security.channel.ProtoSecureChannelProcessor" />
      </list>
    </property>
</bean>

После этого

Некоторые предпочитают прерывать SSL на балансировщике нагрузки и не использовать веб-сервер Apache. В этом случае вы часто принимаете трафик в LB на 80/443, а затем отправляете трафик на Tomcat на 8080.

Если вы используете сопоставление портов Spring:

<sec:port-mappings>
    <sec:port-mapping http="8080" https="443"/>
</sec:port-mappings>

Это не будет работать, поскольку оно не отменяет сопоставление портов в новых канальных процессорах. Вот конфигурация, которая будет работать:

                                                                       

<bean class="org.broadleafcommerce.common.security.channel.ProtoChannelBeanPostProcessor">
    <property name="channelProcessorOverrides">
        <list>
            <bean class="org.broadleafcommerce.common.security.channel.ProtoInsecureChannelProcessor" >
                <property name="entryPoint">
                    <bean class="org.springframework.security.web.access.channel.RetryWithHttpEntryPoint">
                        <property name="portMapper" ref="portMapper"/>
                    </bean>
                </property>
            </bean>
            <bean class="org.broadleafcommerce.common.security.channel.ProtoSecureChannelProcessor" >
                <property name="entryPoint">
                    <bean class="org.springframework.security.web.access.channel.RetryWithHttpsEntryPoint">
                        <property name="portMapper" ref="portMapper"/>
                    </bean>
                </property>
            </bean>
        </list>
    </property>
</bean>

Ссылка ресурса: HTTPS/SSL/ Spring Безопасность не работает как в балансировщике нагрузки, так и при отсутствии нагрузки балансировочная среда # 424

Ответ 3

Вы должны установить соединение HTTPS на LB, тогда у вас будет надлежащее соединение TLS между LB и tomcat, поэтому spring перестанет плакать. Вам просто нужно предоставить самозаверяющий сертификат LB и настроить ваш модуль безопасности spring с помощью закрытого ключа, который сгенерировал этот самоподписанный сертификат.

(более сложный вариант: правильно настроить прокси-сервер tomcat, чтобы заставить его инкапсулировать поток HTTP LB в потоке HTTPS. Устанавливать все требования TLS в прокси: сертификат, закрытый ключ...)

Ответ 4

Вы пытались поместить адрес LB в качестве имени прокси? Это может повлиять на ваше дело.

Ответ 5

Был ли какой-либо из этих ответов дать решение?

У нас похожая проблема с использованием HAProxy перед 2-мя внутренними серверами Tomcat. В настоящее время веб-приложения используют аутентификацию на основе форм. Альтернативные серверы хотят повторно аутентифицировать запросы; наш SysAdmin рекомендовал использовать Spring Security вместо этого для решения этой проблемы или повторной аутентификации, но мы не уверены, что перемещение уровня аутентификации из tomcat в spring решит проблему или просто переместит проблему!

Любое направление будет с благодарностью.