瀏覽代碼

Add RedirectStrategy customization to ChannelSecurityConfigurer for RetryWith classes

Onur Kagan Ozcan 4 年之前
父節點
當前提交
ef25304a30

+ 19 - 1
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.SecurityBuilder;
 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 @@ import org.springframework.security.web.util.matcher.RequestMatcher;
  *
  * @param <H> the type of {@link HttpSecurityBuilder} that is being configured
  * @author Rob Winch
+ * @author Onur Kagan Ozcan
  * @since 3.2
  */
 public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
@@ -86,6 +89,8 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
 
 	private List<ChannelProcessor> channelProcessors;
 
+	private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
+
 	private final ChannelRequestMatcherRegistry REGISTRY;
 
 	/**
@@ -123,9 +128,11 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
 		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 final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
 			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.

+ 46 - 1
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.EnableWe
 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 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
  *
  * @author Rob Winch
  * @author Eleftheria Stein
+ * @author Onur Kagan Ozcan
  */
 @ExtendWith(SpringTestContextExtension.class)
 public class ChannelSecurityConfigurerTests {
@@ -93,6 +101,12 @@ public class ChannelSecurityConfigurerTests {
 		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 @@ public class ChannelSecurityConfigurerTests {
 
 	}
 
+	@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);
+		}
+
+	}
+
 }