Selaa lähdekoodia

Allow configuration of port mapper through nested builder

Issue: gh-5557
Eleftheria Stein 6 vuotta sitten
vanhempi
commit
86f0f84740

+ 46 - 0
config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java

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

+ 55 - 0
config/src/test/java/org/springframework/security/config/annotation/web/configurers/PortMapperConfigurerTests.java

@@ -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
+		}
+	}
 }