diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java index 19fc8ae0ca8..979084ce8c9 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,9 @@ import org.springframework.security.config.annotation.SecurityConfigurer; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.DefaultRedirectStrategy; import org.springframework.security.web.PortMapper; +import org.springframework.security.web.RedirectStrategy; import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl; import org.springframework.security.web.access.channel.ChannelProcessingFilter; import org.springframework.security.web.access.channel.ChannelProcessor; @@ -75,6 +77,7 @@ * * @param the type of {@link HttpSecurityBuilder} that is being configured * @author Rob Winch + * @author Onur Kagan Ozcan * @since 3.2 */ public final class ChannelSecurityConfigurer> @@ -86,6 +89,8 @@ public final class ChannelSecurityConfigurer> private List channelProcessors; + private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); + private final ChannelRequestMatcherRegistry REGISTRY; /** @@ -123,9 +128,11 @@ private List getChannelProcessors(H http) { if (portMapper != null) { RetryWithHttpEntryPoint httpEntryPoint = new RetryWithHttpEntryPoint(); httpEntryPoint.setPortMapper(portMapper); + httpEntryPoint.setRedirectStrategy(this.redirectStrategy); insecureChannelProcessor.setEntryPoint(httpEntryPoint); RetryWithHttpsEntryPoint httpsEntryPoint = new RetryWithHttpsEntryPoint(); httpsEntryPoint.setPortMapper(portMapper); + httpsEntryPoint.setRedirectStrategy(this.redirectStrategy); secureChannelProcessor.setEntryPoint(httpsEntryPoint); } insecureChannelProcessor = postProcess(insecureChannelProcessor); @@ -185,6 +192,17 @@ public ChannelRequestMatcherRegistry channelProcessors(List ch return this; } + /** + * Sets the {@link RedirectStrategy} instances to use in + * {@link RetryWithHttpEntryPoint} and {@link RetryWithHttpsEntryPoint} + * @param redirectStrategy + * @return the {@link ChannelSecurityConfigurer} for further customizations + */ + public ChannelRequestMatcherRegistry redirectStrategy(RedirectStrategy redirectStrategy) { + ChannelSecurityConfigurer.this.redirectStrategy = redirectStrategy; + return this; + } + /** * Return the {@link SecurityBuilder} when done using the * {@link SecurityConfigurer}. This is useful for method chaining. diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java index 041419e50d9..83b2045a842 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configurers/ChannelSecurityConfigurerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,11 @@ package org.springframework.security.config.annotation.web.configurers; +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -27,6 +32,8 @@ import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.test.SpringTestContext; import org.springframework.security.config.test.SpringTestContextExtension; +import org.springframework.security.web.PortMapperImpl; +import org.springframework.security.web.RedirectStrategy; import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl; import org.springframework.security.web.access.channel.ChannelProcessingFilter; import org.springframework.security.web.access.channel.InsecureChannelProcessor; @@ -44,6 +51,7 @@ * * @author Rob Winch * @author Eleftheria Stein + * @author Onur Kagan Ozcan */ @ExtendWith(SpringTestContextExtension.class) public class ChannelSecurityConfigurerTests { @@ -93,6 +101,12 @@ public void requestWhenRequiresChannelConfiguredInLambdaThenRedirectsToHttps() t this.mvc.perform(get("/")).andExpect(redirectedUrl("https://localhost/")); } + @Test + public void requestWhenRequiresChannelConfiguredWithUrlRedirectThenRedirectsToUrlWithHttps() throws Exception { + this.spring.register(RequiresChannelWithTestUrlRedirectStrategy.class).autowire(); + this.mvc.perform(get("/")).andExpect(redirectedUrl("https://localhost/test")); + } + @EnableWebSecurity static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { @@ -155,4 +169,35 @@ protected void configure(HttpSecurity http) throws Exception { } + @EnableWebSecurity + static class RequiresChannelWithTestUrlRedirectStrategy extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http + .portMapper() + .portMapper(new PortMapperImpl()) + .and() + .requiresChannel() + .redirectStrategy(new TestUrlRedirectStrategy()) + .anyRequest() + .requiresSecure(); + // @formatter:on + } + + } + + static class TestUrlRedirectStrategy implements RedirectStrategy { + + @Override + public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) + throws IOException { + String redirectUrl = url + "test"; + redirectUrl = response.encodeRedirectURL(redirectUrl); + response.sendRedirect(redirectUrl); + } + + } + }