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
类以及侦听非安全端口的新Connector
来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。
由于已在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); } }; }