2
0
Эх сурвалжийг харах

Don't cache WebSocket request

PR gh-16741

Signed-off-by: Kevin Yue <yuezk001@gmail.com>
Kevin Yue 5 сар өмнө
parent
commit
7de4217469

+ 5 - 1
config/src/main/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurer.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2024 the original author or authors.
+ * Copyright 2002-2025 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.
@@ -145,6 +145,9 @@ public final class RequestCacheConfigurer<H extends HttpSecurityBuilder<H>>
 		RequestMatcher notFavIcon = new NegatedRequestMatcher(getFaviconRequestMatcher());
 		RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
 				new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
+		RequestMatcher notWebSocket = new NegatedRequestMatcher(
+				new RequestHeaderRequestMatcher("Upgrade", "websocket"));
+
 		boolean isCsrfEnabled = http.getConfigurer(CsrfConfigurer.class) != null;
 		List<RequestMatcher> matchers = new ArrayList<>();
 		if (isCsrfEnabled) {
@@ -156,6 +159,7 @@ public final class RequestCacheConfigurer<H extends HttpSecurityBuilder<H>>
 		matchers.add(notXRequestedWith);
 		matchers.add(notMatchingMediaType(http, MediaType.MULTIPART_FORM_DATA));
 		matchers.add(notMatchingMediaType(http, MediaType.TEXT_EVENT_STREAM));
+		matchers.add(notWebSocket);
 		return new AndRequestMatcher(matchers);
 	}
 

+ 17 - 0
config/src/test/java/org/springframework/security/config/annotation/web/configurers/RequestCacheConfigurerTests.java

@@ -169,6 +169,23 @@ public class RequestCacheConfigurerTests {
 		this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
 	}
 
+	@Test
+	public void getWhenBookmarkedRequestIsWebSocketThenPostAuthenticationRedirectsToRoot() throws Exception {
+		this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();
+		MockHttpServletRequestBuilder request = get("/messages").header("Upgrade", "websocket");
+		// @formatter:off
+		MockHttpSession session = (MockHttpSession) this.mvc.perform(request)
+				.andExpect(redirectedUrl("http://localhost/login"))
+				.andReturn()
+				.getRequest()
+				.getSession();
+		// @formatter:on
+		// ignores websocket
+		// This is desirable since websocket requests are typically not invoked
+		// directly from the browser and we don't want the browser to replay them
+		this.mvc.perform(formLogin(session)).andExpect(redirectedUrl("/"));
+	}
+
 	@Test
 	public void getWhenBookmarkedRequestIsAllMediaTypeThenPostAuthenticationRemembers() throws Exception {
 		this.spring.register(RequestCacheDefaultsConfig.class, DefaultSecurityConfig.class).autowire();