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;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebExchange;
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
* @since 5.0
*/
public class WebSessionServerSecurityContextRepository
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) {
return exchange.getSession()
.doOnNext(session -> {
if(context == null) {
session.getAttributes().remove(SESSION_ATTR);
session.getAttributes().remove(this.springSecurityContextAttrName);
} else {
session.getAttributes().put(SESSION_ATTR, context);
session.getAttributes().put(this.springSecurityContextAttrName, context);
}
})
.flatMap(session -> session.changeSessionId());
@ -43,7 +62,7 @@ public class WebSessionServerSecurityContextRepository
public Mono<SecurityContext> load(ServerWebExchange exchange) {
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);
});
}

View File

@ -39,7 +39,23 @@ public class WebSessionServerSecurityContextRepositoryTests {
@Test
public void saveAndLoadWhenDefaultsThenFound() {
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();
@ -49,7 +65,7 @@ public class WebSessionServerSecurityContextRepositoryTests {
@Test
public void saveAndLoadWhenNullThenDeletes() {
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();
SecurityContext actual = this.repository.load(this.exchange).block();