Add new interfaces for CSRF request processing

Issue gh-4001
Issue gh-11456
This commit is contained in:
Steve Riesenberg
2022-08-11 16:29:56 -05:00
committed by Steve Riesenberg
parent ff6fd78d64
commit 86fbb8db07
18 changed files with 572 additions and 59 deletions

View File

@@ -34,8 +34,10 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
/**
* @author Rob Winch
@@ -72,6 +74,25 @@ public class CsrfAuthenticationStrategyTests {
assertThatIllegalArgumentException().isThrownBy(() -> new CsrfAuthenticationStrategy(null));
}
@Test
public void setRequestAttributeHandlerWhenNullThenIllegalStateException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.strategy.setRequestAttributeHandler(null))
.withMessage("requestAttributeHandler cannot be null");
}
@Test
public void onAuthenticationWhenCustomRequestAttributeHandlerThenUsed() {
given(this.csrfTokenRepository.loadToken(this.request)).willReturn(this.existingToken);
given(this.csrfTokenRepository.generateToken(this.request)).willReturn(this.generatedToken);
CsrfTokenRequestAttributeHandler requestAttributeHandler = mock(CsrfTokenRequestAttributeHandler.class);
this.strategy.setRequestAttributeHandler(requestAttributeHandler);
this.strategy.onAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER"), this.request,
this.response);
verify(requestAttributeHandler).handle(eq(this.request), eq(this.response), any());
verifyNoMoreInteractions(requestAttributeHandler);
}
@Test
public void logoutRemovesCsrfTokenAndSavesNew() {
given(this.csrfTokenRepository.loadToken(this.request)).willReturn(this.existingToken);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -335,6 +335,30 @@ public class CsrfFilterTests {
assertThat(this.response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
}
@Test
public void doFilterWhenRequestAttributeHandlerThenUsed() throws Exception {
given(this.requestMatcher.matches(this.request)).willReturn(true);
given(this.tokenRepository.loadToken(this.request)).willReturn(this.token);
CsrfTokenRequestAttributeHandler requestAttributeHandler = mock(CsrfTokenRequestAttributeHandler.class);
this.filter.setRequestAttributeHandler(requestAttributeHandler);
this.request.setParameter(this.token.getParameterName(), this.token.getToken());
this.filter.doFilter(this.request, this.response, this.filterChain);
verify(requestAttributeHandler).handle(eq(this.request), eq(this.response), any());
verify(this.filterChain).doFilter(this.request, this.response);
}
@Test
public void doFilterWhenRequestResolverThenUsed() throws Exception {
given(this.requestMatcher.matches(this.request)).willReturn(true);
given(this.tokenRepository.loadToken(this.request)).willReturn(this.token);
CsrfTokenRequestResolver requestResolver = mock(CsrfTokenRequestResolver.class);
given(requestResolver.resolveCsrfTokenValue(this.request, this.token)).willReturn(this.token.getToken());
this.filter.setRequestResolver(requestResolver);
this.filter.doFilter(this.request, this.response, this.filterChain);
verify(requestResolver).resolveCsrfTokenValue(this.request, this.token);
verify(this.filterChain).doFilter(this.request, this.response);
}
@Test
public void setRequireCsrfProtectionMatcherNull() {
assertThatIllegalArgumentException().isThrownBy(() -> this.filter.setRequireCsrfProtectionMatcher(null));
@@ -351,7 +375,9 @@ public class CsrfFilterTests {
throws ServletException, IOException {
CsrfFilter filter = createCsrfFilter(this.tokenRepository);
String csrfAttrName = "_csrf";
filter.setCsrfRequestAttributeName(csrfAttrName);
CsrfTokenRequestProcessor csrfTokenRequestProcessor = new CsrfTokenRequestProcessor();
csrfTokenRequestProcessor.setCsrfRequestAttributeName(csrfAttrName);
filter.setRequestAttributeHandler(csrfTokenRequestProcessor);
CsrfToken expectedCsrfToken = mock(CsrfToken.class);
given(this.tokenRepository.loadToken(this.request)).willReturn(expectedCsrfToken);

View File

@@ -0,0 +1,134 @@
/*
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.web.csrf;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Tests for {@link CsrfTokenRequestProcessor}.
*
* @author Steve Riesenberg
* @since 5.8
*/
public class CsrfTokenRequestProcessorTests {
private MockHttpServletRequest request;
private MockHttpServletResponse response;
private CsrfToken token;
private CsrfTokenRequestProcessor processor;
@BeforeEach
public void setup() {
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
this.token = new DefaultCsrfToken("headerName", "paramName", "csrfTokenValue");
this.processor = new CsrfTokenRequestProcessor();
}
@Test
public void handleWhenRequestIsNullThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.processor.handle(null, this.response, () -> this.token))
.withMessage("request cannot be null");
}
@Test
public void handleWhenResponseIsNullThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.processor.handle(this.request, null, () -> this.token))
.withMessage("response cannot be null");
}
@Test
public void handleWhenCsrfTokenSupplierIsNullThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.processor.handle(this.request, this.response, null))
.withMessage("csrfToken supplier cannot be null");
}
@Test
public void handleWhenCsrfTokenIsNullThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.processor.handle(this.request, this.response, () -> null))
.withMessage("csrfToken cannot be null");
}
@Test
public void handleWhenCsrfRequestAttributeSetThenUsed() {
this.processor.setCsrfRequestAttributeName("_csrf");
this.processor.handle(this.request, this.response, () -> this.token);
assertThat(this.request.getAttribute(CsrfToken.class.getName())).isEqualTo(this.token);
assertThat(this.request.getAttribute("_csrf")).isEqualTo(this.token);
}
@Test
public void handleWhenValidParametersThenRequestAttributesSet() {
this.processor.handle(this.request, this.response, () -> this.token);
assertThat(this.request.getAttribute(CsrfToken.class.getName())).isEqualTo(this.token);
assertThat(this.request.getAttribute(this.token.getParameterName())).isEqualTo(this.token);
}
@Test
public void resolveCsrfTokenValueWhenRequestIsNullThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.processor.resolveCsrfTokenValue(null, this.token))
.withMessage("request cannot be null");
}
@Test
public void resolveCsrfTokenValueWhenCsrfTokenIsNullThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.processor.resolveCsrfTokenValue(this.request, null))
.withMessage("csrfToken cannot be null");
}
@Test
public void resolveCsrfTokenValueWhenTokenNotSetThenReturnsNull() {
String tokenValue = this.processor.resolveCsrfTokenValue(this.request, this.token);
assertThat(tokenValue).isNull();
}
@Test
public void resolveCsrfTokenValueWhenParameterSetThenReturnsTokenValue() {
this.request.setParameter(this.token.getParameterName(), this.token.getToken());
String tokenValue = this.processor.resolveCsrfTokenValue(this.request, this.token);
assertThat(tokenValue).isEqualTo(this.token.getToken());
}
@Test
public void resolveCsrfTokenValueWhenHeaderSetThenReturnsTokenValue() {
this.request.addHeader(this.token.getHeaderName(), this.token.getToken());
String tokenValue = this.processor.resolveCsrfTokenValue(this.request, this.token);
assertThat(tokenValue).isEqualTo(this.token.getToken());
}
@Test
public void resolveCsrfTokenValueWhenHeaderAndParameterSetThenHeaderIsPreferred() {
this.request.addHeader(this.token.getHeaderName(), "header");
this.request.setParameter(this.token.getParameterName(), "parameter");
String tokenValue = this.processor.resolveCsrfTokenValue(this.request, this.token);
assertThat(tokenValue).isEqualTo("header");
}
}