Allow configuration of session fixation and concurrency through nested builder

Issue: gh-5557
This commit is contained in:
Eleftheria Stein 2019-07-12 13:53:55 -04:00
parent 4b2539df10
commit 7961b819aa
3 changed files with 95 additions and 4 deletions

View File

@ -681,8 +681,11 @@ public final class HttpSecurity extends
* )
* .sessionManagement(sessionManagement ->
* sessionManagement
* .maximumSessions(1)
* .expiredUrl("/login?expired")
* .sessionConcurrency(sessionConcurrency ->
* sessionConcurrency
* .maximumSessions(1)
* .expiredUrl("/login?expired")
* )
* );
* }
* }

View File

@ -26,6 +26,7 @@ import org.springframework.context.ApplicationListener;
import org.springframework.context.event.GenericApplicationListenerAdapter;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
@ -249,6 +250,19 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
return new SessionFixationConfigurer();
}
/**
* Allows configuring session fixation protection.
*
* @param sessionFixationCustomizer the {@link Customizer} to provide more options for
* the {@link SessionFixationConfigurer}
* @return the {@link SessionManagementConfigurer} for further customizations
*/
public SessionManagementConfigurer<H> sessionFixation(Customizer<SessionFixationConfigurer> sessionFixationCustomizer)
throws Exception {
sessionFixationCustomizer.customize(new SessionFixationConfigurer());
return this;
}
/**
* Controls the maximum number of sessions for a user. The default is to allow any
* number of users.
@ -260,6 +274,20 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
return new ConcurrencyControlConfigurer();
}
/**
* Controls the maximum number of sessions for a user. The default is to allow any
* number of users.
*
* @param sessionConcurrencyCustomizer the {@link Customizer} to provide more options for
* the {@link ConcurrencyControlConfigurer}
* @return the {@link SessionManagementConfigurer} for further customizations
*/
public SessionManagementConfigurer<H> sessionConcurrency(Customizer<ConcurrencyControlConfigurer> sessionConcurrencyCustomizer)
throws Exception {
sessionConcurrencyCustomizer.customize(new ConcurrencyControlConfigurer());
return this;
}
/**
* Invokes {@link #postProcess(Object)} and sets the
* {@link SessionAuthenticationStrategy} for session fixation.
@ -338,6 +366,18 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
*/
public final class ConcurrencyControlConfigurer {
/**
* Controls the maximum number of sessions for a user. The default is to allow any
* number of users.
*
* @param maximumSessions the maximum number of sessions for a user
* @return the {@link ConcurrencyControlConfigurer} for further customizations
*/
public ConcurrencyControlConfigurer maximumSessions(int maximumSessions) {
SessionManagementConfigurer.this.maximumSessions = maximumSessions;
return this;
}
/**
* The URL to redirect to if a user tries to access a resource and their session
* has been expired due to too many sessions for the current user. The default is

View File

@ -202,6 +202,51 @@ public class SessionManagementConfigurerTests {
}
}
@Test
public void authenticateWhenNewSessionFixationProtectionInLambdaThenCreatesNewSession() throws Exception {
this.spring.register(SFPNewSessionInLambdaConfig.class).autowire();
MockHttpSession givenSession = new MockHttpSession();
String givenSessionId = givenSession.getId();
givenSession.setAttribute("name", "value");
MockHttpSession resultingSession = (MockHttpSession)
this.mvc.perform(get("/auth")
.session(givenSession)
.with(httpBasic("user", "password")))
.andExpect(status().isNotFound())
.andReturn().getRequest().getSession(false);
assertThat(givenSessionId).isNotEqualTo(resultingSession.getId());
assertThat(resultingSession.getAttribute("name")).isNull();
}
@EnableWebSecurity
static class SFPNewSessionInLambdaConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.sessionManagement(sessionManagement ->
sessionManagement
.sessionFixation(sessionFixation ->
sessionFixation.newSession()
)
)
.httpBasic(withDefaults());
// @formatter:on
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// @formatter:off
auth
.inMemoryAuthentication()
.withUser(PasswordEncodedUser.user());
// @formatter:on
}
}
@Test
public void loginWhenUserLoggedInAndMaxSessionsIsOneThenLoginPrevented() throws Exception {
this.spring.register(ConcurrencyControlConfig.class).autowire();
@ -289,8 +334,11 @@ public class SessionManagementConfigurerTests {
.formLogin(withDefaults())
.sessionManagement(sessionManagement ->
sessionManagement
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.sessionConcurrency(sessionConcurrency ->
sessionConcurrency
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
)
);
// @formatter:on
}