Skip to content

Commit 1636ffd

Browse files
committed
Add logging to CsrfTokenRequestHandler implementations
Add trace-level logging to show the logical path of CSRF token processing - Log token source (header or parameter) in resolveCsrfTokenValue - Log request attribute names in handle methods - Log failures in XorCsrfTokenRequestAttributeHandler (especially Base64 decoding) - Add similar logging to XorServerCsrfTokenRequestAttributeHandler Improves debugging capabilities without changing functionality. Signed-off-by: yybmion <[email protected]>
1 parent 55de634 commit 1636ffd

File tree

4 files changed

+65
-13
lines changed

4 files changed

+65
-13
lines changed

web/src/main/java/org/springframework/security/web/csrf/CsrfTokenRequestAttributeHandler.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 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.
@@ -21,6 +21,9 @@
2121
import jakarta.servlet.http.HttpServletRequest;
2222
import jakarta.servlet.http.HttpServletResponse;
2323

24+
import org.apache.commons.logging.Log;
25+
import org.apache.commons.logging.LogFactory;
26+
import org.springframework.core.log.LogMessage;
2427
import org.springframework.util.Assert;
2528

2629
/**
@@ -29,10 +32,13 @@
2932
* value as either a header or parameter value of the request.
3033
*
3134
* @author Steve Riesenberg
35+
* @author Yoobin Yoon
3236
* @since 5.8
3337
*/
3438
public class CsrfTokenRequestAttributeHandler implements CsrfTokenRequestHandler {
3539

40+
private static final Log logger = LogFactory.getLog(CsrfTokenRequestAttributeHandler.class);
41+
3642
private String csrfRequestAttributeName = "_csrf";
3743

3844
/**
@@ -60,6 +66,9 @@ public void handle(HttpServletRequest request, HttpServletResponse response,
6066
String csrfAttrName = (this.csrfRequestAttributeName != null) ? this.csrfRequestAttributeName
6167
: csrfToken.getParameterName();
6268
request.setAttribute(csrfAttrName, csrfToken);
69+
70+
logger.trace(LogMessage.format("CSRF token written to request attributes: %s, %s", CsrfToken.class.getName(),
71+
csrfAttrName));
6372
}
6473

6574
@SuppressWarnings("serial")

web/src/main/java/org/springframework/security/web/csrf/CsrfTokenRequestHandler.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 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.
@@ -16,11 +16,12 @@
1616

1717
package org.springframework.security.web.csrf;
1818

19-
import java.util.function.Supplier;
20-
2119
import jakarta.servlet.http.HttpServletRequest;
2220
import jakarta.servlet.http.HttpServletResponse;
23-
21+
import java.util.function.Supplier;
22+
import org.apache.commons.logging.Log;
23+
import org.apache.commons.logging.LogFactory;
24+
import org.springframework.core.log.LogMessage;
2425
import org.springframework.util.Assert;
2526

2627
/**
@@ -30,12 +31,15 @@
3031
* available to the application through request attributes.
3132
*
3233
* @author Steve Riesenberg
34+
* @author Yoobin Yoon
3335
* @since 5.8
3436
* @see CsrfTokenRequestAttributeHandler
3537
*/
3638
@FunctionalInterface
3739
public interface CsrfTokenRequestHandler extends CsrfTokenRequestResolver {
3840

41+
Log logger = LogFactory.getLog(CsrfTokenRequestHandler.class);
42+
3943
/**
4044
* Handles a request using a {@link CsrfToken}.
4145
* @param request the {@code HttpServletRequest} being handled
@@ -51,6 +55,13 @@ default String resolveCsrfTokenValue(HttpServletRequest request, CsrfToken csrfT
5155
String actualToken = request.getHeader(csrfToken.getHeaderName());
5256
if (actualToken == null) {
5357
actualToken = request.getParameter(csrfToken.getParameterName());
58+
if (actualToken != null) {
59+
logger.trace(
60+
LogMessage.format("CSRF token found in request parameter: %s", csrfToken.getParameterName()));
61+
}
62+
}
63+
else {
64+
logger.trace(LogMessage.format("CSRF token found in request header: %s", csrfToken.getHeaderName()));
5465
}
5566
return actualToken;
5667
}

web/src/main/java/org/springframework/security/web/csrf/XorCsrfTokenRequestAttributeHandler.java

Lines changed: 24 additions & 6 deletions
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.
@@ -16,13 +16,14 @@
1616

1717
package org.springframework.security.web.csrf;
1818

19+
import jakarta.servlet.http.HttpServletRequest;
20+
import jakarta.servlet.http.HttpServletResponse;
1921
import java.security.SecureRandom;
2022
import java.util.Base64;
2123
import java.util.function.Supplier;
22-
23-
import jakarta.servlet.http.HttpServletRequest;
24-
import jakarta.servlet.http.HttpServletResponse;
25-
24+
import org.apache.commons.logging.Log;
25+
import org.apache.commons.logging.LogFactory;
26+
import org.springframework.core.log.LogMessage;
2627
import org.springframework.security.crypto.codec.Utf8;
2728
import org.springframework.util.Assert;
2829

@@ -32,10 +33,13 @@
3233
* value from the masked value as either a header or parameter value of the request.
3334
*
3435
* @author Steve Riesenberg
36+
* @author Yoobin Yoon
3537
* @since 5.8
3638
*/
3739
public final class XorCsrfTokenRequestAttributeHandler extends CsrfTokenRequestAttributeHandler {
3840

41+
private static final Log logger = LogFactory.getLog(XorCsrfTokenRequestAttributeHandler.class);
42+
3943
private SecureRandom secureRandom = new SecureRandom();
4044

4145
/**
@@ -55,6 +59,7 @@ public void handle(HttpServletRequest request, HttpServletResponse response,
5559
Assert.notNull(response, "response cannot be null");
5660
Assert.notNull(deferredCsrfToken, "deferredCsrfToken cannot be null");
5761
Supplier<CsrfToken> updatedCsrfToken = deferCsrfTokenUpdate(deferredCsrfToken);
62+
logger.trace(LogMessage.format("XOR CSRF token created and will be written to request attributes"));
5863
super.handle(request, response, updatedCsrfToken);
5964
}
6065

@@ -70,7 +75,18 @@ private Supplier<CsrfToken> deferCsrfTokenUpdate(Supplier<CsrfToken> csrfTokenSu
7075
@Override
7176
public String resolveCsrfTokenValue(HttpServletRequest request, CsrfToken csrfToken) {
7277
String actualToken = super.resolveCsrfTokenValue(request, csrfToken);
73-
return getTokenValue(actualToken, csrfToken.getToken());
78+
if (actualToken == null) {
79+
logger.trace(LogMessage.format("No CSRF token value found in request"));
80+
return null;
81+
}
82+
String tokenValue = getTokenValue(actualToken, csrfToken.getToken());
83+
if (tokenValue == null) {
84+
logger.trace(LogMessage.format("CSRF token validation failed"));
85+
}
86+
else {
87+
logger.trace(LogMessage.format("CSRF token successfully validated"));
88+
}
89+
return tokenValue;
7490
}
7591

7692
private static String getTokenValue(String actualToken, String token) {
@@ -79,12 +95,14 @@ private static String getTokenValue(String actualToken, String token) {
7995
actualBytes = Base64.getUrlDecoder().decode(actualToken);
8096
}
8197
catch (Exception ex) {
98+
logger.trace(LogMessage.format("Failed to find CSRF token since Base64 decoding failed"), ex);
8299
return null;
83100
}
84101

85102
byte[] tokenBytes = Utf8.encode(token);
86103
int tokenSize = tokenBytes.length;
87104
if (actualBytes.length != tokenSize * 2) {
105+
logger.trace(LogMessage.format("Failed to validate CSRF token since token length is invalid"));
88106
return null;
89107
}
90108

web/src/main/java/org/springframework/security/web/server/csrf/XorServerCsrfTokenRequestAttributeHandler.java

Lines changed: 16 additions & 2 deletions
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.
@@ -19,6 +19,9 @@
1919
import java.security.SecureRandom;
2020
import java.util.Base64;
2121

22+
import org.apache.commons.logging.Log;
23+
import org.apache.commons.logging.LogFactory;
24+
import org.springframework.core.log.LogMessage;
2225
import reactor.core.publisher.Mono;
2326

2427
import org.springframework.security.crypto.codec.Utf8;
@@ -32,10 +35,13 @@
3235
* masked value as either a form data value or header of the request.
3336
*
3437
* @author Steve Riesenberg
38+
* @author Yoobin Yoon
3539
* @since 5.8
3640
*/
3741
public final class XorServerCsrfTokenRequestAttributeHandler extends ServerCsrfTokenRequestAttributeHandler {
3842

43+
private static final Log logger = LogFactory.getLog(XorServerCsrfTokenRequestAttributeHandler.class);
44+
3945
private SecureRandom secureRandom = new SecureRandom();
4046

4147
/**
@@ -57,13 +63,19 @@ public void handle(ServerWebExchange exchange, Mono<CsrfToken> csrfToken) {
5763
createXoredCsrfToken(this.secureRandom, token.getToken())))
5864
.cast(CsrfToken.class)
5965
.cache();
66+
logger.trace(LogMessage.format("XOR CSRF token created and will be written to exchange attributes"));
6067
super.handle(exchange, updatedCsrfToken);
6168
}
6269

6370
@Override
6471
public Mono<String> resolveCsrfTokenValue(ServerWebExchange exchange, CsrfToken csrfToken) {
6572
return super.resolveCsrfTokenValue(exchange, csrfToken)
66-
.flatMap((actualToken) -> Mono.justOrEmpty(getTokenValue(actualToken, csrfToken.getToken())));
73+
.flatMap((actualToken) -> Mono.justOrEmpty(getTokenValue(actualToken, csrfToken.getToken())))
74+
.doOnNext(tokenValue -> {
75+
if (tokenValue != null) {
76+
logger.trace(LogMessage.format("CSRF token successfully validated"));
77+
}
78+
});
6779
}
6880

6981
private static String getTokenValue(String actualToken, String token) {
@@ -72,12 +84,14 @@ private static String getTokenValue(String actualToken, String token) {
7284
actualBytes = Base64.getUrlDecoder().decode(actualToken);
7385
}
7486
catch (Exception ex) {
87+
logger.trace(LogMessage.format("Failed to find CSRF token since Base64 decoding failed"), ex);
7588
return null;
7689
}
7790

7891
byte[] tokenBytes = Utf8.encode(token);
7992
int tokenSize = tokenBytes.length;
8093
if (actualBytes.length != tokenSize * 2) {
94+
logger.trace(LogMessage.format("Failed to validate CSRF token since token length is invalid"));
8195
return null;
8296
}
8397

0 commit comments

Comments
 (0)