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

WebSessionSecurityContextRepository custom session attribute name

Fixes: gh-4843
Rob Winch 7 жил өмнө
parent
commit
8d30d6110b

+ 24 - 5
web/src/main/java/org/springframework/security/web/server/context/WebSessionServerSecurityContextRepository.java

@@ -16,26 +16,45 @@
 package org.springframework.security.web.server.context;
 package org.springframework.security.web.server.context;
 
 
 import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.context.SecurityContext;
+import org.springframework.util.Assert;
 import org.springframework.web.server.ServerWebExchange;
 import org.springframework.web.server.ServerWebExchange;
 
 
 import reactor.core.publisher.Mono;
 import reactor.core.publisher.Mono;
 
 
 /**
 /**
- *
+ * Stores the {@link SecurityContext} in the
+ * {@link org.springframework.web.server.WebSession}. When a {@link SecurityContext} is
+ * saved, the session id is changed to prevent session fixation attacks.
  * @author Rob Winch
  * @author Rob Winch
  * @since 5.0
  * @since 5.0
  */
  */
 public class WebSessionServerSecurityContextRepository
 public class WebSessionServerSecurityContextRepository
 	implements ServerSecurityContextRepository {
 	implements ServerSecurityContextRepository {
-	final String SESSION_ATTR = "USER";
+
+	/**
+	 * The default session attribute name to save and load the {@link SecurityContext}
+	 */
+	public static final String DEFAULT_SPRING_SECURITY_CONTEXT_ATTR_NAME = "SPRING_SECURITY_CONTEXT";
+
+	private String springSecurityContextAttrName = DEFAULT_SPRING_SECURITY_CONTEXT_ATTR_NAME;
+
+	/**
+	 * Sets the session attribute name used to save and load the {@link SecurityContext}
+	 * @param springSecurityContextAttrName the session attribute name to use to save and
+	 * load the {@link SecurityContext}
+	 */
+	public void setSpringSecurityContextAttrName(String springSecurityContextAttrName) {
+		Assert.hasText(springSecurityContextAttrName, "springSecurityContextAttrName cannot be null or empty");
+		this.springSecurityContextAttrName = springSecurityContextAttrName;
+	}
 
 
 	public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
 	public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
 		return exchange.getSession()
 		return exchange.getSession()
 			.doOnNext(session -> {
 			.doOnNext(session -> {
 				if(context == null) {
 				if(context == null) {
-					session.getAttributes().remove(SESSION_ATTR);
+					session.getAttributes().remove(this.springSecurityContextAttrName);
 				} else {
 				} else {
-					session.getAttributes().put(SESSION_ATTR, context);
+					session.getAttributes().put(this.springSecurityContextAttrName, context);
 				}
 				}
 			})
 			})
 			.flatMap(session -> session.changeSessionId());
 			.flatMap(session -> session.changeSessionId());
@@ -43,7 +62,7 @@ public class WebSessionServerSecurityContextRepository
 
 
 	public Mono<SecurityContext> load(ServerWebExchange exchange) {
 	public Mono<SecurityContext> load(ServerWebExchange exchange) {
 		return exchange.getSession().flatMap( session -> {
 		return exchange.getSession().flatMap( session -> {
-			SecurityContext context = (SecurityContext) session.getAttributes().get(SESSION_ATTR);
+			SecurityContext context = (SecurityContext) session.getAttributes().get(this.springSecurityContextAttrName);
 			return context == null ? Mono.empty() : Mono.just(context);
 			return context == null ? Mono.empty() : Mono.just(context);
 		});
 		});
 	}
 	}

+ 18 - 2
web/src/test/java/org/springframework/security/web/server/context/WebSessionServerSecurityContextRepositoryTests.java

@@ -39,7 +39,23 @@ public class WebSessionServerSecurityContextRepositoryTests {
 	@Test
 	@Test
 	public void saveAndLoadWhenDefaultsThenFound() {
 	public void saveAndLoadWhenDefaultsThenFound() {
 		SecurityContext expected = new SecurityContextImpl();
 		SecurityContext expected = new SecurityContextImpl();
-		this.repository.save(this.exchange, new SecurityContextImpl()).block();
+		this.repository.save(this.exchange, expected).block();
+
+		SecurityContext actual = this.repository.load(this.exchange).block();
+
+		assertThat(actual).isEqualTo(expected);
+	}
+
+	@Test
+	public void saveAndLoadWhenCustomAttributeThenFound() {
+		String attrName = "attr";
+		this.repository.setSpringSecurityContextAttrName(attrName);
+		SecurityContext expected = new SecurityContextImpl();
+
+		this.repository.save(this.exchange, expected).block();
+
+		WebSession session = this.exchange.getSession().block();
+		assertThat(session.<SecurityContext>getAttribute(attrName)).isEqualTo(expected);
 
 
 		SecurityContext actual = this.repository.load(this.exchange).block();
 		SecurityContext actual = this.repository.load(this.exchange).block();
 
 
@@ -49,7 +65,7 @@ public class WebSessionServerSecurityContextRepositoryTests {
 	@Test
 	@Test
 	public void saveAndLoadWhenNullThenDeletes() {
 	public void saveAndLoadWhenNullThenDeletes() {
 		SecurityContext context = new SecurityContextImpl();
 		SecurityContext context = new SecurityContextImpl();
-		this.repository.save(this.exchange, new SecurityContextImpl()).block();
+		this.repository.save(this.exchange, context).block();
 		this.repository.save(this.exchange, null).block();
 		this.repository.save(this.exchange, null).block();
 
 
 		SecurityContext actual = this.repository.load(this.exchange).block();
 		SecurityContext actual = this.repository.load(this.exchange).block();