Allow configuration of port mapper through nested builder

Issue: gh-5557
This commit is contained in:
Eleftheria Stein 2019-06-28 13:43:41 -04:00
parent 6fbea88e1e
commit 86f0f84740
2 changed files with 101 additions and 0 deletions

View File

@ -633,6 +633,52 @@ public final class HttpSecurity extends
return getOrApply(new PortMapperConfigurer<>());
}
/**
* Allows configuring a {@link PortMapper} that is available from
* {@link HttpSecurity#getSharedObject(Class)}. Other provided
* {@link SecurityConfigurer} objects use this configured {@link PortMapper} as a
* default {@link PortMapper} when redirecting from HTTP to HTTPS or from HTTPS to
* HTTP (for example when used in combination with {@link #requiresChannel()}. By
* default Spring Security uses a {@link PortMapperImpl} which maps the HTTP port 8080
* to the HTTPS port 8443 and the HTTP port of 80 to the HTTPS port of 443.
*
* <h2>Example Configuration</h2>
*
* The following configuration will ensure that redirects within Spring Security from
* HTTP of a port of 9090 will redirect to HTTPS port of 9443 and the HTTP port of 80
* to the HTTPS port of 443.
*
* <pre>
* &#064;Configuration
* &#064;EnableWebSecurity
* public class PortMapperSecurityConfig extends WebSecurityConfigurerAdapter {
*
* &#064;Override
* protected void configure(HttpSecurity http) throws Exception {
* http
* .requiresChannel()
* .anyRequest().requiresSecure()
* .and()
* .portMapper(portMapper ->
* portMapper
* .http(9090).mapsTo(9443)
* .http(80).mapsTo(443)
* );
* }
* }
* </pre>
*
* @see #requiresChannel()
* @param portMapperCustomizer the {@link Customizer} to provide more options for
* the {@link PortMapperConfigurer}
* @return the {@link HttpSecurity} for further customizations
* @throws Exception
*/
public HttpSecurity portMapper(Customizer<PortMapperConfigurer<HttpSecurity>> portMapperCustomizer) throws Exception {
portMapperCustomizer.customize(getOrApply(new PortMapperConfigurer<>()));
return HttpSecurity.this;
}
/**
* Configures container based pre authentication. In this case, authentication
* is managed by the Servlet Container.

View File

@ -22,8 +22,11 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.test.SpringTestRule;
import org.springframework.security.web.PortMapperImpl;
import org.springframework.test.web.servlet.MockMvc;
import java.util.Collections;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
@ -61,4 +64,56 @@ public class PortMapperConfigurerTests {
.portMapper();
}
}
@Test
public void requestWhenPortMapperHttpMapsToInLambdaThenRedirectsToHttpsPort() throws Exception {
this.spring.register(HttpMapsToInLambdaConfig.class).autowire();
this.mockMvc.perform(get("http://localhost:543"))
.andExpect(redirectedUrl("https://localhost:123"));
}
@EnableWebSecurity
static class HttpMapsToInLambdaConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.requiresChannel()
.anyRequest().requiresSecure()
.and()
.portMapper(portMapper ->
portMapper
.http(543).mapsTo(123)
);
// @formatter:on
}
}
@Test
public void requestWhenCustomPortMapperInLambdaThenRedirectsToHttpsPort() throws Exception {
this.spring.register(CustomPortMapperInLambdaConfig.class).autowire();
this.mockMvc.perform(get("http://localhost:543"))
.andExpect(redirectedUrl("https://localhost:123"));
}
@EnableWebSecurity
static class CustomPortMapperInLambdaConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
PortMapperImpl customPortMapper = new PortMapperImpl();
customPortMapper.setPortMappings(Collections.singletonMap("543", "123"));
// @formatter:off
http
.requiresChannel()
.anyRequest().requiresSecure()
.and()
.portMapper(portMapper ->
portMapper
.portMapper(customPortMapper)
);
// @formatter:on
}
}
}