Add RedirectStrategy customization to ChannelSecurityConfigurer for RetryWith classes

This commit is contained in:
Onur Kagan Ozcan 2021-08-12 11:20:36 +03:00 committed by Rob Winch
parent 0c201565fc
commit aa0f788f59
2 changed files with 65 additions and 2 deletions

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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.SecurityConfigurer;
import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 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.PortMapper;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl; import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl;
import org.springframework.security.web.access.channel.ChannelProcessingFilter; import org.springframework.security.web.access.channel.ChannelProcessingFilter;
import org.springframework.security.web.access.channel.ChannelProcessor; 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 * @param <H> the type of {@link HttpSecurityBuilder} that is being configured
* @author Rob Winch * @author Rob Winch
* @author Onur Kagan Ozcan
* @since 3.2 * @since 3.2
*/ */
public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>> 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 List<ChannelProcessor> channelProcessors;
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
private final ChannelRequestMatcherRegistry REGISTRY; private final ChannelRequestMatcherRegistry REGISTRY;
/** /**
@ -123,9 +128,11 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
if (portMapper != null) { if (portMapper != null) {
RetryWithHttpEntryPoint httpEntryPoint = new RetryWithHttpEntryPoint(); RetryWithHttpEntryPoint httpEntryPoint = new RetryWithHttpEntryPoint();
httpEntryPoint.setPortMapper(portMapper); httpEntryPoint.setPortMapper(portMapper);
httpEntryPoint.setRedirectStrategy(this.redirectStrategy);
insecureChannelProcessor.setEntryPoint(httpEntryPoint); insecureChannelProcessor.setEntryPoint(httpEntryPoint);
RetryWithHttpsEntryPoint httpsEntryPoint = new RetryWithHttpsEntryPoint(); RetryWithHttpsEntryPoint httpsEntryPoint = new RetryWithHttpsEntryPoint();
httpsEntryPoint.setPortMapper(portMapper); httpsEntryPoint.setPortMapper(portMapper);
httpsEntryPoint.setRedirectStrategy(this.redirectStrategy);
secureChannelProcessor.setEntryPoint(httpsEntryPoint); secureChannelProcessor.setEntryPoint(httpsEntryPoint);
} }
insecureChannelProcessor = postProcess(insecureChannelProcessor); insecureChannelProcessor = postProcess(insecureChannelProcessor);
@ -185,6 +192,17 @@ public final class ChannelSecurityConfigurer<H extends HttpSecurityBuilder<H>>
return this; 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 * Return the {@link SecurityBuilder} when done using the
* {@link SecurityConfigurer}. This is useful for method chaining. * {@link SecurityConfigurer}. This is useful for method chaining.

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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; 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.Test;
import org.junit.jupiter.api.extension.ExtendWith; 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.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.test.SpringTestContext; import org.springframework.security.config.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension; 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.ChannelDecisionManagerImpl;
import org.springframework.security.web.access.channel.ChannelProcessingFilter; import org.springframework.security.web.access.channel.ChannelProcessingFilter;
import org.springframework.security.web.access.channel.InsecureChannelProcessor; 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 Rob Winch
* @author Eleftheria Stein * @author Eleftheria Stein
* @author Onur Kagan Ozcan
*/ */
@ExtendWith(SpringTestContextExtension.class) @ExtendWith(SpringTestContextExtension.class)
public class ChannelSecurityConfigurerTests { public class ChannelSecurityConfigurerTests {
@ -93,6 +101,12 @@ public class ChannelSecurityConfigurerTests {
this.mvc.perform(get("/")).andExpect(redirectedUrl("https://localhost/")); 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 @EnableWebSecurity
static class ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter { 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);
}
}
} }