Skip to content

Commit c5e8562

Browse files
committed
feature: Add failure handler for cookie verification
This feature allows to customize the behaviour of what should be done in case the cookie could not be verified. By default the cookie is silently ignored, as before. Closes #1
1 parent 0472318 commit c5e8562

File tree

5 files changed

+128
-4
lines changed

5 files changed

+128
-4
lines changed

pom.xml

+10
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@
9696
<artifactId>assertj-core</artifactId>
9797
<version>3.10.0</version>
9898
</dependency>
99+
<dependency>
100+
<groupId>org.mockito</groupId>
101+
<artifactId>mockito-core</artifactId>
102+
<version>2.19.0</version>
103+
</dependency>
99104
<dependency>
100105
<groupId>com.fasterxml.jackson</groupId>
101106
<artifactId>jackson-bom</artifactId>
@@ -145,6 +150,11 @@
145150
<artifactId>junit-jupiter-engine</artifactId>
146151
<scope>test</scope>
147152
</dependency>
153+
<dependency>
154+
<groupId>org.mockito</groupId>
155+
<artifactId>mockito-core</artifactId>
156+
<scope>test</scope>
157+
</dependency>
148158
<dependency>
149159
<groupId>org.springframework</groupId>
150160
<artifactId>spring-test</artifactId>

src/main/java/com/innoq/spring/cookie/flash/CookieFlashMapManager.java

+11-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package com.innoq.spring.cookie.flash;
1717

1818
import com.innoq.spring.cookie.flash.codec.FlashMapListCodec;
19+
import com.innoq.spring.cookie.flash.verification.CookieVerificationFailureHandler;
1920
import com.innoq.spring.cookie.security.CookieValueSigner;
2021
import org.springframework.util.Assert;
2122
import org.springframework.web.servlet.FlashMap;
@@ -37,6 +38,8 @@ public final class CookieFlashMapManager extends AbstractFlashMapManager {
3738
private final FlashMapListCodec codec;
3839
private final CookieValueSigner signer;
3940
private final String cookieName;
41+
private CookieVerificationFailureHandler verificationFailureHandler =
42+
CookieVerificationFailureHandler.ignoreFailures();
4043

4144
public CookieFlashMapManager(FlashMapListCodec codec,
4245
CookieValueSigner signer) {
@@ -53,6 +56,12 @@ public CookieFlashMapManager(FlashMapListCodec codec,
5356
this.cookieName = cookieName;
5457
}
5558

59+
public void setVerificationFailureHandler(
60+
CookieVerificationFailureHandler verificationFailureHandler) {
61+
Assert.notNull(verificationFailureHandler, "CookieVerificationFailureHandler must not be null");
62+
this.verificationFailureHandler = verificationFailureHandler;
63+
}
64+
5665
@Override
5766
protected List<FlashMap> retrieveFlashMaps(HttpServletRequest request) {
5867
final Cookie cookie = getCookie(request, cookieName);
@@ -88,16 +97,14 @@ protected Object getFlashMapsMutex(HttpServletRequest request) {
8897
private List<FlashMap> decode(String value) {
8998
final String[] signatureAndPayload = reverse(value).split("--", 2);
9099
if (signatureAndPayload.length != 2) {
91-
// TODO logging
92-
return null;
100+
return verificationFailureHandler.onInvalidValue(value);
93101
}
94102

95103
final String signature = reverse(signatureAndPayload[0]);
96104
final String payload = reverse(signatureAndPayload[1]);
97105

98106
if (!isVerified(payload, signature)) {
99-
// TODO logging
100-
return null;
107+
return verificationFailureHandler.onInvalidSignature(payload, signature);
101108
}
102109

103110
return codec.decode(payload);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright 2018 innoQ Deutschland GmbH
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.innoq.spring.cookie.flash.verification;
17+
18+
import org.springframework.web.servlet.FlashMap;
19+
20+
import java.util.List;
21+
22+
public interface CookieVerificationFailureHandler {
23+
24+
List<FlashMap> onInvalidValue(String value);
25+
26+
List<FlashMap> onInvalidSignature(String payload, String signature);
27+
28+
static CookieVerificationFailureHandler ignoreFailures() {
29+
return IgnoreCookieVerificationFailureHandler.INSTANCE;
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* Copyright 2018 innoQ Deutschland GmbH
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.innoq.spring.cookie.flash.verification;
17+
18+
import org.springframework.web.servlet.FlashMap;
19+
20+
import java.util.List;
21+
22+
enum IgnoreCookieVerificationFailureHandler
23+
implements CookieVerificationFailureHandler {
24+
INSTANCE;
25+
26+
@Override
27+
public List<FlashMap> onInvalidValue(String value) {
28+
return null;
29+
}
30+
31+
@Override
32+
public List<FlashMap> onInvalidSignature(String payload, String signature) {
33+
return null;
34+
}
35+
}

src/test/java/com/innoq/spring/cookie/flash/CookieFlashMapManagerTest.java

+41
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package com.innoq.spring.cookie.flash;
1717

1818
import com.innoq.spring.cookie.flash.codec.jackson.JacksonFlashMapListCodec;
19+
import com.innoq.spring.cookie.flash.verification.CookieVerificationFailureHandler;
1920
import com.innoq.spring.cookie.security.CookieValueSigner;
2021
import org.junit.jupiter.api.Test;
2122
import org.springframework.mock.web.MockHttpServletRequest;
@@ -30,6 +31,9 @@
3031
import static java.util.Collections.emptyList;
3132
import static org.assertj.core.api.Assertions.assertThat;
3233
import static org.assertj.core.api.Assertions.entry;
34+
import static org.mockito.Mockito.mock;
35+
import static org.mockito.Mockito.verify;
36+
import static org.mockito.Mockito.when;
3337

3438
class CookieFlashMapManagerTest {
3539

@@ -65,6 +69,43 @@ void retrieveFlashMaps_withValidCookie_returnsFlashMaps() {
6569
assertThat(flashMap.getTargetRequestPath()).isEqualTo("/foo");
6670
}
6771

72+
@Test
73+
void retrieveFlashMaps_withInvalidCookieValue_callsGivenVerificationFailureHandlerAndUsesItsReturnValue() {
74+
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
75+
request.setCookies(new Cookie("flash", "ABCDEF"));
76+
77+
CookieVerificationFailureHandler verificationFailureHandler =
78+
mock(CookieVerificationFailureHandler.class);
79+
when(verificationFailureHandler.onInvalidValue("ABCDEF")).thenReturn(null);
80+
81+
sut.setVerificationFailureHandler(verificationFailureHandler);
82+
83+
List<FlashMap> flashMaps = sut.retrieveFlashMaps(request);
84+
85+
assertThat(flashMaps).isNull();
86+
verify(verificationFailureHandler).onInvalidValue("ABCDEF");
87+
}
88+
89+
@Test
90+
void retrieveFlashMaps_withInvalidCookieValueSignatur_callsGivenVerificationFailureHandlerAndUsesItsReturnValue() {
91+
String cookieValue = "abcd--efgh";
92+
93+
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
94+
request.setCookies(new Cookie("flash", cookieValue));
95+
96+
CookieVerificationFailureHandler verificationFailureHandler =
97+
mock(CookieVerificationFailureHandler.class);
98+
when(verificationFailureHandler.onInvalidSignature("abcd", "efgh"))
99+
.thenReturn(null);
100+
101+
sut.setVerificationFailureHandler(verificationFailureHandler);
102+
103+
List<FlashMap> flashMaps = sut.retrieveFlashMaps(request);
104+
105+
assertThat(flashMaps).isNull();
106+
verify(verificationFailureHandler).onInvalidSignature("abcd", "efgh");
107+
}
108+
68109
@Test
69110
void updateFlashMaps_withSingleFlashMap_writesCookie() {
70111
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");

0 commit comments

Comments
 (0)