Default to Xor CSRF tokens in CsrfFilter
Issue gh-11960
This commit is contained in:
+9
-2
@@ -51,8 +51,11 @@ import org.springframework.security.web.context.SecurityContextHolderFilter;
|
||||
import org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter;
|
||||
import org.springframework.security.web.csrf.CsrfFilter;
|
||||
import org.springframework.security.web.csrf.CsrfToken;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRequestHandler;
|
||||
import org.springframework.security.web.csrf.DefaultCsrfToken;
|
||||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler;
|
||||
import org.springframework.security.web.header.HeaderWriterFilter;
|
||||
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
|
||||
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
||||
@@ -121,8 +124,12 @@ public class DefaultFiltersTests {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest("POST", "");
|
||||
request.setServletPath("/logout");
|
||||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
|
||||
new HttpSessionCsrfTokenRepository().saveToken(csrfToken, request, response);
|
||||
request.setParameter(csrfToken.getParameterName(), csrfToken.getToken());
|
||||
CsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
|
||||
repository.saveToken(csrfToken, request, response);
|
||||
CsrfTokenRequestHandler handler = new XorCsrfTokenRequestAttributeHandler();
|
||||
handler.handle(request, response, () -> csrfToken);
|
||||
CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
|
||||
request.setParameter(token.getParameterName(), token.getToken());
|
||||
this.spring.getContext().getBean("springSecurityFilterChain", Filter.class).doFilter(request, response,
|
||||
new MockFilterChain());
|
||||
assertThat(response.getRedirectedUrl()).isEqualTo("/login?logout");
|
||||
|
||||
+24
-12
@@ -85,7 +85,9 @@ public class DefaultLoginPageConfigurerTests {
|
||||
String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login").sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect(content().string("<!DOCTYPE html>\n"
|
||||
.andExpect((result) -> {
|
||||
CsrfToken token = (CsrfToken) result.getRequest().getAttribute(CsrfToken.class.getName());
|
||||
assertThat(result.getResponse().getContentAsString()).isEqualTo("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
@@ -108,11 +110,12 @@ public class DefaultLoginPageConfigurerTests {
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ "<input name=\"" + token.getParameterName() + "\" type=\"hidden\" value=\"" + token.getToken() + "\" />\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>"));
|
||||
+ "</body></html>");
|
||||
});
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@@ -131,7 +134,9 @@ public class DefaultLoginPageConfigurerTests {
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login?error").session((MockHttpSession) mvcResult.getRequest().getSession())
|
||||
.sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect(content().string("<!DOCTYPE html>\n"
|
||||
.andExpect((result) -> {
|
||||
CsrfToken token = (CsrfToken) result.getRequest().getAttribute(CsrfToken.class.getName());
|
||||
assertThat(result.getResponse().getContentAsString()).isEqualTo("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
@@ -153,11 +158,12 @@ public class DefaultLoginPageConfigurerTests {
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ "<input name=\"" + token.getParameterName() + "\" type=\"hidden\" value=\"" + token.getToken() + "\" />\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>"));
|
||||
+ "</body></html>");
|
||||
});
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@@ -180,7 +186,9 @@ public class DefaultLoginPageConfigurerTests {
|
||||
String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login?logout").sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect(content().string("<!DOCTYPE html>\n"
|
||||
.andExpect((result) -> {
|
||||
CsrfToken token = (CsrfToken) result.getRequest().getAttribute(CsrfToken.class.getName());
|
||||
assertThat(result.getResponse().getContentAsString()).isEqualTo("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
@@ -203,11 +211,12 @@ public class DefaultLoginPageConfigurerTests {
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ "<input name=\"" + token.getParameterName() + "\" type=\"hidden\" value=\"" + token.getToken() + "\" />\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>"));
|
||||
+ "</body></html>");
|
||||
});
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@@ -230,7 +239,9 @@ public class DefaultLoginPageConfigurerTests {
|
||||
String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login").sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect(content().string("<!DOCTYPE html>\n"
|
||||
.andExpect((result) -> {
|
||||
CsrfToken token = (CsrfToken) result.getRequest().getAttribute(CsrfToken.class.getName());
|
||||
assertThat(result.getResponse().getContentAsString()).isEqualTo("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
@@ -254,11 +265,12 @@ public class DefaultLoginPageConfigurerTests {
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ "<p><input type='checkbox' name='remember-me'/> Remember me on this computer.</p>\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ "<input name=\"" + token.getParameterName() + "\" type=\"hidden\" value=\"" + token.getToken() + "\" />\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>"));
|
||||
+ "</body></html>");
|
||||
});
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
||||
+7
-2
@@ -39,7 +39,10 @@ import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.context.HttpRequestResponseHolder;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.springframework.security.web.csrf.CsrfToken;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRequestHandler;
|
||||
import org.springframework.security.web.csrf.DeferredCsrfToken;
|
||||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -82,8 +85,10 @@ public class SessionManagementConfigurerServlet31Tests {
|
||||
request.setParameter("username", "user");
|
||||
request.setParameter("password", "password");
|
||||
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
|
||||
CsrfToken token = repository.generateToken(request);
|
||||
repository.saveToken(token, request, this.response);
|
||||
CsrfTokenRequestHandler handler = new XorCsrfTokenRequestAttributeHandler();
|
||||
DeferredCsrfToken deferredCsrfToken = repository.loadDeferredToken(request, this.response);
|
||||
handler.handle(request, this.response, deferredCsrfToken::get);
|
||||
CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
|
||||
request.setParameter(token.getParameterName(), token.getToken());
|
||||
request.getSession().setAttribute("attribute1", "value1");
|
||||
loadConfig(SessionManagementDefaultSessionFixationServlet31Config.class);
|
||||
|
||||
Reference in New Issue
Block a user