在 Spring Boot 中将 HTTP 定向到代理后面的 HTTPS

Posted

技术标签:

【中文标题】在 Spring Boot 中将 HTTP 定向到代理后面的 HTTPS【英文标题】:Direct HTTP to HTTPS behind a Proxy in Spring Boot 【发布时间】:2019-05-15 08:51:28 【问题描述】:

我有一个用 Spring Boot (2.0.5) 编写的服务器。它位于提供 SSL 的代理服务器后面。代理接受 HTTP (80) 和 HTTPS (443) 并将两者都转发到我的服务器,该服务器仅接受端口 2222 上的 HTTP。代理设置以下请求标头。

x-转发-for x-forwarded-proto x 转发端口

我在WebSecurityConfig 类中测试了以下代码,但没有成功。

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception 
     httpSecurity.requiresChannel().anyRequest().requiresSecure()
     .and().
     ...  

我还编写了以下代码来将 HTTP 重定向到 HTTPS。但它也会重定向 HTTPS 流量。但我只需要重定向 HTTP。

import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class HttpsConfiguration 

    @Bean
    public ServletWebServerFactory servletContainer() 
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() 

            @Override
            protected void postProcessContext(Context context) 
                SecurityConstraint securityConstraint = new SecurityConstraint();
                securityConstraint.setUserConstraint("CONFIDENTIAL");
                SecurityCollection collection = new SecurityCollection();
                collection.addPattern("/*");
                securityConstraint.addCollection(collection);
                context.addConstraint(securityConstraint);
            
        ;
        return tomcat;
    

我正在寻找一种检查请求标头的方法,如果是 HTTP,我想将其重定向到 HTTPS。

【问题讨论】:

【参考方案1】:

您提供的 Spring Security 配置应该可以工作。我猜问题是你没有正确地set up Spring Boot to work with proxies。要启用支持,您应该指定:

server.use-forward-headers=true

注意:如果您的应用程序在 Cloud Foundry 或 Heroku 中运行,则 server.use-forward-headers 属性默认为 true。在所有其他情况下,它默认为 false。

我会特别关注details around Tomcat。这就是导致大多数人出现问题的原因。 Tomcat 依靠附加设置来确定内部代理 IP 地址是否与默认正则表达式匹配。如果您的代理的 IP 与正则表达式不匹配,它会默默地忽略转发的标头。

如果您在这方面遇到困难,请尝试指定以下内容:

server.tomcat.internal-proxies=.*

注意:其他应用程序服务器不关心代理 IP 地址,如果客户端可以欺骗 X Forwarded 标头,那么它也可以欺骗 IP 地址,因此向每个 IP 地址开放它不会对你的申请。

【讨论】:

这些属性只对嵌入式tomcat服务器有效吧?

以上是关于在 Spring Boot 中将 HTTP 定向到代理后面的 HTTPS的主要内容,如果未能解决你的问题,请参考以下文章

在spring boot中将控制从一个控制器重定向到另一个控制器

(spring-boot) http 到 https 重定向,405 方法不允许消息

Spring Boot 将 HTTP 重定向到 HTTPS

Elastic Beanstalk 和 Spring Boot 将 HTTP 重定向到 HTTPS

负载均衡器后面带有 Spring Security 的 Spring Boot:将 HTTP 重定向到 HTTPS

在 Spring Boot 应用程序中为 AWS Beanstalk 的 nginx 设置 HTTP 到 HTTPS 重定向