Parcourir la source

Add Set-Cookie header value for XSRF-TOKEN

This commit fixes an issue where using HttpServletResponse#setHeader
causes previous header values to be overwritten.

Closes gh-13075
Steve Riesenberg il y a 2 ans
Parent
commit
07b884a2cb

+ 2 - 2
web/src/main/java/org/springframework/security/web/csrf/CookieCsrfTokenRepository.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2022 the original author or authors.
+ * Copyright 2012-2023 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.
@@ -97,7 +97,7 @@ public final class CookieCsrfTokenRepository implements CsrfTokenRepository {
 
 		this.cookieCustomizer.accept(cookieBuilder);
 
-		response.setHeader(HttpHeaders.SET_COOKIE, cookieBuilder.build().toString());
+		response.addHeader(HttpHeaders.SET_COOKIE, cookieBuilder.build().toString());
 
 		// Set request attribute to signal that response has blank cookie value,
 		// which allows loadToken to return null when token has been removed

+ 13 - 1
web/src/test/java/org/springframework/security/web/csrf/CookieCsrfTokenRepositoryTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-2023 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.
@@ -20,6 +20,7 @@ import jakarta.servlet.http.Cookie;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import org.springframework.http.HttpHeaders;
 import org.springframework.mock.web.MockCookie;
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
@@ -290,6 +291,17 @@ class CookieCsrfTokenRepositoryTests {
 		assertThat(((MockCookie) tokenCookie).getSameSite()).isEqualTo(sameSitePolicy);
 	}
 
+	// gh-13075
+	@Test
+	void saveTokenWithExistingSetCookieThenDoesNotOverwrite() {
+		this.response.setHeader(HttpHeaders.SET_COOKIE, "MyCookie=test");
+		this.repository = new CookieCsrfTokenRepository();
+		CsrfToken token = this.repository.generateToken(this.request);
+		this.repository.saveToken(token, this.request, this.response);
+		assertThat(this.response.getCookie("MyCookie")).isNotNull();
+		assertThat(this.response.getCookie(CookieCsrfTokenRepository.DEFAULT_CSRF_COOKIE_NAME)).isNotNull();
+	}
+
 	@Test
 	void loadTokenNoCookiesNull() {
 		assertThat(this.repository.loadToken(this.request)).isNull();