首页 文章

Spring Boot将HTTP重定向到HTTPS

提问于
浏览
27

对于基于Spring Boot的应用程序,我在application.properties上配置了ssl属性,请参阅我的配置:

server.port=8443
server.ssl.key-alias=tomcat
server.ssl.key-password=123456
server.ssl.key-store=classpath:key.p12
server.ssl.key-store-provider=SunJSSE
server.ssl.key-store-type=pkcs12

我在Application.class上添加了连接,就像

@Bean
public EmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
    final TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
    factory.addAdditionalTomcatConnectors(this.createConnection());
    return factory;
}

private Connector createConnection() {
    final String protocol = "org.apache.coyote.http11.Http11NioProtocol";
    final Connector connector = new Connector(protocol);

    connector.setScheme("http");
    connector.setPort(9090);
    connector.setRedirectPort(8443);
    return connector;
}

但是,当我尝试以下时

http://127.0.0.1:9090/

重定向到

https://127.0.0.1:8443/

没有执行 . 谁遇到过类似的问题?

7 回答

  • 9

    要使Tomcat执行重定向,您需要使用一个或多个安全约束对其进行配置 . 您可以通过使用 TomcatEmbeddedServletContainerFactory 子类对 Context 进行后处理来完成此操作 .

    例如:

    TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
        @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);
        }
    };
    

    由于 CONFIDENTIAL/* ,这将导致Tomcat将每个请求重定向到HTTPS . 如果需要更多地控制重定向和未重定向的内容,可以配置多个模式和多个约束 .

  • 3

    在应用程序* .properties文件中设置此属性(以及在代理服务器后面运行的HTTPS标头的相应servlet特定配置)并设置Spring Security(例如,使用org.springframework.boot:spring-boot-你的类路径上的starter-security应该足够了:

    security.require-ssl=true
    

    现在,出于某种原因,在禁用基本身份验证时(至少在旧版本的Spring Boot上),配置不受尊重 . 因此,在这种情况下,您需要采取额外的步骤,并通过手动配置代码的安全性来自己尊重它,如下所示:

    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Inject private SecurityProperties securityProperties;
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            if (securityProperties.isRequireSsl()) http.requiresChannel().anyRequest().requiresSecure();
        }
    }
    

    因此,如果您在代理后面使用Tomcat,您将在应用程序* .properties文件中拥有所有这些属性:

    security.require-ssl=true
    
    server.tomcat.remote_ip_header=x-forwarded-for
    server.tomcat.protocol_header=x-forwarded-proto
    
  • 30

    批准的答案对我来说还不够 .

    我还必须将以下内容添加到我的Web安全配置中,因为我没有使用默认的8080端口:

    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private Environment environment;
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            // other security configuration missing
    
            http.portMapper()
                    .http(Integer.parseInt(environment.getProperty("server.http.port"))) // http port defined in yml config file
                    .mapsTo(Integer.parseInt(environment.getProperty("server.port"))); // https port defined in yml config file
    
            // we only need https on /auth
            http.requiresChannel()
                    .antMatchers("/auth/**").requiresSecure()
                    .anyRequest().requiresInsecure();
        }
    }
    
  • 6

    只需2个步骤 .

    1-在pom.xml中添加spring security dependency

    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    

    2-在应用程序的根包上添加此类 .

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.requiresChannel().anyRequest().requiresSecure();
        }
    }
    
  • 25

    在Spring-Boot中,需要以下依赖

    步骤1-

    <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    

    步骤2-只需要在application.properties文件上进行以下配置

    - server.port=8443
     - server.ssl.key.alias=ode-https
     - server.ssl.key-store-type=JKS (just for testing i USED JSK, but for production normally use pkcs12)
     - server.ssl.key-password=password
     - server.ssl.key-store=classpath:ode-https.jks
    

    步骤3-现在需要使用上述细节生成证书 .

    keytool -genkey -alias ode-https -storetype JKS -keyalg RSA -keys ize 2048 -validity 365 -keystore ode-https.jks

    步骤4-将证书移动到程序中的资源文件夹 .

    步骤5-创建配置类

    @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);
                }
            };
            tomcat.addAdditionalTomcatConnectors(redirectConnector());
            return tomcat;
        }
    
        @Value("${server.port.http}") //Defined in application.properties file
        int httpPort;
    
        @Value("${server.port}") //Defined in application.properties file
        int httpsPort;
    
        private Connector redirectConnector() {
            Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
            connector.setScheme("http");
            connector.setPort(httpPort);
            connector.setSecure(false);
            connector.setRedirectPort(httpsPort);
            return connector;
        }
    }
    

    而已 .

  • 4

    对于Jetty(使用9.2.14测试),您需要为_2495850添加额外的配置(根据您的喜好调整 pathSpec ):

    import org.eclipse.jetty.security.ConstraintMapping;
    import org.eclipse.jetty.security.ConstraintSecurityHandler;
    import org.eclipse.jetty.util.security.Constraint;
    import org.eclipse.jetty.webapp.AbstractConfiguration;
    import org.eclipse.jetty.webapp.WebAppContext;
    
    class HttpToHttpsJettyConfiguration extends AbstractConfiguration
    {
        // http://wiki.eclipse.org/Jetty/Howto/Configure_SSL#Redirecting_http_requests_to_https
        @Override
        public void configure(WebAppContext context) throws Exception
        {
            Constraint constraint = new Constraint();
            constraint.setDataConstraint(2);
    
            ConstraintMapping constraintMapping = new ConstraintMapping();
            constraintMapping.setPathSpec("/*");
            constraintMapping.setConstraint(constraint);
    
            ConstraintSecurityHandler constraintSecurityHandler = new ConstraintSecurityHandler();
            constraintSecurityHandler.addConstraintMapping(constraintMapping);
    
            context.setSecurityHandler(constraintSecurityHandler);
        }
    }
    

    然后通过添加一个实现 EmbeddedServletContainerCustomizer@Configuration 类以及一个侦听非安全端口的新 Connector 来连接此类:

    @Configuration
    public class HttpToHttpsJettyCustomizer implements EmbeddedServletContainerCustomizer
    {
        @Override
        public void customize(ConfigurableEmbeddedServletContainer container)
        {
            JettyEmbeddedServletContainerFactory containerFactory = (JettyEmbeddedServletContainerFactory) container;
            //Add a plain HTTP connector and a WebAppContext config to force redirect from http->https
            containerFactory.addConfigurations(new HttpToHttpsJettyConfiguration());
    
            containerFactory.addServerCustomizers(server -> {
                HttpConfiguration http = new HttpConfiguration();
                http.setSecurePort(443);
                http.setSecureScheme("https");
    
                ServerConnector connector = new ServerConnector(server);
                connector.addConnectionFactory(new HttpConnectionFactory(http));
                connector.setPort(80);
    
                server.addConnector(connector);
            });
        }
    }
    

    这意味着SSL Connector 已经配置并在此示例中侦听端口443 .

  • 2

    从Spring Boot 2中的TomcatEmbeddedServletContainerFactory has been removed开始,使用:

    @Bean
    public TomcatServletWebServerFactory httpsRedirectConfig() {
        return 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);
            }
        };
    }
    

相关问题