2
0
Эх сурвалжийг харах

Allow configuration of session fixation and concurrency through nested builder

Issue: gh-5557
Eleftheria Stein 6 жил өмнө
parent
commit
7961b819aa

+ 5 - 2
config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java

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

+ 40 - 0
config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java

@@ -26,6 +26,7 @@ import org.springframework.context.ApplicationListener;
 import org.springframework.context.event.GenericApplicationListenerAdapter;
 import org.springframework.context.event.GenericApplicationListenerAdapter;
 import org.springframework.context.event.SmartApplicationListener;
 import org.springframework.context.event.SmartApplicationListener;
 import org.springframework.security.authentication.AuthenticationTrustResolver;
 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.HttpSecurityBuilder;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.config.http.SessionCreationPolicy;
@@ -249,6 +250,19 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
 		return new SessionFixationConfigurer();
 		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
 	 * Controls the maximum number of sessions for a user. The default is to allow any
 	 * number of users.
 	 * number of users.
@@ -260,6 +274,20 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
 		return new ConcurrencyControlConfigurer();
 		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
 	 * Invokes {@link #postProcess(Object)} and sets the
 	 * {@link SessionAuthenticationStrategy} for session fixation.
 	 * {@link SessionAuthenticationStrategy} for session fixation.
@@ -338,6 +366,18 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
 	 */
 	 */
 	public final class ConcurrencyControlConfigurer {
 	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
 		 * 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
 		 * has been expired due to too many sessions for the current user. The default is

+ 50 - 2
config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.java

@@ -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
 	@Test
 	public void loginWhenUserLoggedInAndMaxSessionsIsOneThenLoginPrevented() throws Exception {
 	public void loginWhenUserLoggedInAndMaxSessionsIsOneThenLoginPrevented() throws Exception {
 		this.spring.register(ConcurrencyControlConfig.class).autowire();
 		this.spring.register(ConcurrencyControlConfig.class).autowire();
@@ -289,8 +334,11 @@ public class SessionManagementConfigurerTests {
 				.formLogin(withDefaults())
 				.formLogin(withDefaults())
 				.sessionManagement(sessionManagement ->
 				.sessionManagement(sessionManagement ->
 					sessionManagement
 					sessionManagement
-						.maximumSessions(1)
-						.maxSessionsPreventsLogin(true)
+						.sessionConcurrency(sessionConcurrency ->
+							sessionConcurrency
+								.maximumSessions(1)
+								.maxSessionsPreventsLogin(true)
+						)
 				);
 				);
 			// @formatter:on
 			// @formatter:on
 		}
 		}