Spring Boot将HTTP重定向到HTTPS

对于基于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/ 

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

要使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。 如果需要更多控制重定向和不重定向,可以配置多个模式和多个约束。

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

 security.require-ssl=true 

现在,出于某种原因,在禁用基本身份validation时(至少在旧版本的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 

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

我还必须将以下内容添加到我的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(); } } 

只需2个步骤。

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

   org.springframework.boot spring-boot-starter-security  

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

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

对于Jetty(使用9.2.14测试),您需要为WebAppContext添加额外配置(根据您的喜好调整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类以及侦听非安全端口的新ConnectorConnector此类:

 @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。

由于已在Spring Boot 2中删除了TomcatEmbeddedServletContainerFactory ,请使用以下命令:

 @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); } }; }