Skip to content

Commit 09f8287

Browse files
committed
Don't cache WebSocket request
PR gh-16741 Signed-off-by: Kevin Yue <[email protected]>
1 parent 0938ca0 commit 09f8287

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -145,6 +145,9 @@ private RequestMatcher createDefaultSavedRequestMatcher(H http) {
145145
RequestMatcher notFavIcon = new NegatedRequestMatcher(getFaviconRequestMatcher());
146146
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
147147
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
148+
RequestMatcher notWebSocket = new NegatedRequestMatcher(
149+
new RequestHeaderRequestMatcher("Upgrade", "websocket"));
150+
148151
boolean isCsrfEnabled = http.getConfigurer(CsrfConfigurer.class) != null;
149152
List<RequestMatcher> matchers = new ArrayList<>();
150153
if (isCsrfEnabled) {
@@ -156,6 +159,7 @@ private RequestMatcher createDefaultSavedRequestMatcher(H http) {
156159
matchers.add(notXRequestedWith);
157160
matchers.add(notMatchingMediaType(http, MediaType.MULTIPART_FORM_DATA));
158161
matchers.add(notMatchingMediaType(http, MediaType.TEXT_EVENT_STREAM));
162+
matchers.add(notWebSocket);
159163
return new AndRequestMatcher(matchers);
160164
}
161165

config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java

+17
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,23 @@ public void getWhenBookmarkedRequestIsTextEventStreamThenPostAuthenticationRedir
169169
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
170170
}
171171

172+
@Test
173+
public void getWhenBookmarkedRequestIsWebSocketThenPostAuthenticationRedirectsToRoot() throws Exception {
174+
this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();
175+
MockHttpServletRequestBuilder request = get("/messages").header("Upgrade", "websocket");
176+
// @formatter:off
177+
MockHttpSession session = (MockHttpSession) this.mvc.perform(request)
178+
.andExpect(redirectedUrl("http://localhost/login"))
179+
.andReturn()
180+
.getRequest()
181+
.getSession();
182+
// @formatter:on
183+
// ignores websocket
184+
// This is desirable since websocket requests are typically not invoked
185+
// directly from the browser and we don't want the browser to replay them
186+
this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
187+
}
188+
172189
@Test
173190
public void getWhenBookmarkedRequestIsAllMediaTypeThenPostAuthenticationRemembers() throws Exception {
174191
this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();

0 commit comments

Comments
 (0)