WebSessionSecurityContextRepository custom session attribute name

Fixes: gh-4843
This commit is contained in:
Rob Winch 2017-11-16 13:20:21 -06:00
parent b7529be3d0
commit 8d30d6110b
2 changed files with 42 additions and 7 deletions

View File

@ -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);
}); });
} }

View File

@ -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();