mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-01 09:42:13 +00:00
Cache Xor CsrfToken
Closes gh-11988
This commit is contained in:
parent
ffbcaca24a
commit
05e4a1dd20
@ -59,12 +59,12 @@ public final class XorCsrfTokenRequestAttributeHandler extends CsrfTokenRequestA
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Supplier<CsrfToken> deferCsrfTokenUpdate(Supplier<CsrfToken> csrfTokenSupplier) {
|
private Supplier<CsrfToken> deferCsrfTokenUpdate(Supplier<CsrfToken> csrfTokenSupplier) {
|
||||||
return () -> {
|
return new CachedCsrfTokenSupplier(() -> {
|
||||||
CsrfToken csrfToken = csrfTokenSupplier.get();
|
CsrfToken csrfToken = csrfTokenSupplier.get();
|
||||||
Assert.state(csrfToken != null, "csrfToken supplier returned null");
|
Assert.state(csrfToken != null, "csrfToken supplier returned null");
|
||||||
String updatedToken = createXoredCsrfToken(this.secureRandom, csrfToken.getToken());
|
String updatedToken = createXoredCsrfToken(this.secureRandom, csrfToken.getToken());
|
||||||
return new DefaultCsrfToken(csrfToken.getHeaderName(), csrfToken.getParameterName(), updatedToken);
|
return new DefaultCsrfToken(csrfToken.getHeaderName(), csrfToken.getParameterName(), updatedToken);
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -123,4 +123,24 @@ public final class XorCsrfTokenRequestAttributeHandler extends CsrfTokenRequestA
|
|||||||
return xoredCsrf;
|
return xoredCsrf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class CachedCsrfTokenSupplier implements Supplier<CsrfToken> {
|
||||||
|
|
||||||
|
private final Supplier<CsrfToken> delegate;
|
||||||
|
|
||||||
|
private CsrfToken csrfToken;
|
||||||
|
|
||||||
|
private CachedCsrfTokenSupplier(Supplier<CsrfToken> delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CsrfToken get() {
|
||||||
|
if (this.csrfToken == null) {
|
||||||
|
this.csrfToken = this.delegate.get();
|
||||||
|
}
|
||||||
|
return this.csrfToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,8 @@ public final class XorServerCsrfTokenRequestAttributeHandler extends ServerCsrfT
|
|||||||
Assert.notNull(exchange, "exchange cannot be null");
|
Assert.notNull(exchange, "exchange cannot be null");
|
||||||
Assert.notNull(csrfToken, "csrfToken cannot be null");
|
Assert.notNull(csrfToken, "csrfToken cannot be null");
|
||||||
Mono<CsrfToken> updatedCsrfToken = csrfToken.map((token) -> new DefaultCsrfToken(token.getHeaderName(),
|
Mono<CsrfToken> updatedCsrfToken = csrfToken.map((token) -> new DefaultCsrfToken(token.getHeaderName(),
|
||||||
token.getParameterName(), createXoredCsrfToken(this.secureRandom, token.getToken())));
|
token.getParameterName(), createXoredCsrfToken(this.secureRandom, token.getToken())))
|
||||||
|
.cast(CsrfToken.class).cache();
|
||||||
super.handle(exchange, updatedCsrfToken);
|
super.handle(exchange, updatedCsrfToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,6 +148,15 @@ public class XorCsrfTokenRequestAttributeHandlerTests {
|
|||||||
assertThat(csrfTokenAttribute.getToken()).isEqualTo(XOR_CSRF_TOKEN_VALUE);
|
assertThat(csrfTokenAttribute.getToken()).isEqualTo(XOR_CSRF_TOKEN_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handleWhenCsrfTokenRequestedTwiceThenCached() {
|
||||||
|
this.handler.handle(this.request, this.response, () -> this.token);
|
||||||
|
|
||||||
|
CsrfToken csrfTokenAttribute = (CsrfToken) this.request.getAttribute(CsrfToken.class.getName());
|
||||||
|
assertThat(csrfTokenAttribute.getToken()).isNotEqualTo(this.token.getToken());
|
||||||
|
assertThat(csrfTokenAttribute.getToken()).isEqualTo(csrfTokenAttribute.getToken());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveCsrfTokenValueWhenRequestIsNullThenThrowsIllegalArgumentException() {
|
public void resolveCsrfTokenValueWhenRequestIsNullThenThrowsIllegalArgumentException() {
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> this.handler.resolveCsrfTokenValue(null, this.token))
|
assertThatIllegalArgumentException().isThrownBy(() -> this.handler.resolveCsrfTokenValue(null, this.token))
|
||||||
|
@ -110,6 +110,17 @@ public class XorServerCsrfTokenRequestAttributeHandlerTests {
|
|||||||
verify(this.secureRandom).nextBytes(anyByteArray());
|
verify(this.secureRandom).nextBytes(anyByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handleWhenCsrfTokenRequestedTwiceThenCached() {
|
||||||
|
this.handler.handle(this.exchange, Mono.just(this.token));
|
||||||
|
Mono<CsrfToken> csrfTokenAttribute = this.exchange.getAttribute(CsrfToken.class.getName());
|
||||||
|
assertThat(csrfTokenAttribute).isNotNull();
|
||||||
|
CsrfToken csrfToken1 = csrfTokenAttribute.block();
|
||||||
|
CsrfToken csrfToken2 = csrfTokenAttribute.block();
|
||||||
|
assertThat(csrfToken1.getToken()).isNotEqualTo(this.token.getToken());
|
||||||
|
assertThat(csrfToken1.getToken()).isEqualTo(csrfToken2.getToken());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveCsrfTokenValueWhenExchangeIsNullThenThrowsIllegalArgumentException() {
|
public void resolveCsrfTokenValueWhenExchangeIsNullThenThrowsIllegalArgumentException() {
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> this.handler.resolveCsrfTokenValue(null, this.token))
|
assertThatIllegalArgumentException().isThrownBy(() -> this.handler.resolveCsrfTokenValue(null, this.token))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user