Hello,
Just wanted to follow-up, as I was able to get this working with the following
configuration:
My WebApplication class has a request cycle listener to set a csrf token as
metadata:
```
...
public static final MetaDataKey<CsrfToken> CSRF_TOKEN_KEY = new MetaDataKey<>()
{};
...
@Override
protected void init() {
...
setRootRequestMapper(new CryptoMapper(getRootRequestMapper(), this));
getRequestCycleListeners().add(new
ResourceIsolationRequestCycleListener());
getRequestCycleListeners().add(new IRequestCycleListener() {
@Override
public void onBeginRequest(RequestCycle cycle) {
HttpServletRequest request = (HttpServletRequest)
cycle.getRequest().getContainerRequest();
CsrfToken token = (CsrfToken)
request.getAttribute(CsrfToken.class.getName());
if (token != null) {
cycle.setMetaData(CSRF_TOKEN_KEY, token);
}
IRequestCycleListener.super.onBeginRequest(cycle);
}
});
}
```
Then, my BasePage (extended by all pages) leverages this and sets to set the
request header via Wicket.Event.subscribe:
```
@Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
CsrfToken token =
RequestCycle.get().getMetaData(CsurpsWebApplication.CSRF_TOKEN_KEY);
if (token != null) {
response.render(StringHeaderItem.forString(String.format("<meta
name=\"_csrf\" content=\"%s\"/>", token.getToken())));
response.render(StringHeaderItem.forString(String.format("<meta
name=\"_csrf_header\" content=\"%s\"/>", token.getHeaderName())));
response.render(JavaScriptHeaderItem.forReference(new
PackageResourceReference(BasePage.class, "csrf.js")));
}
}
```
csrf.js:
```
(function() {
var csrfToken = document.querySelector('meta[name="_csrf"]')?.content;
var csrfHeader =
document.querySelector('meta[name="_csrf_header"]')?.content;
if (csrfToken && csrfHeader && window.Wicket && Wicket.Event &&
Wicket.Ajax) {
Wicket.Event.subscribe('/ajax/call/beforeSend', function(jqEvent,
attributes, jqXHR, settings) {
jqXHR.setRequestHeader(csrfHeader, csrfToken);
});
}
})();
```
So at this point, Spring csrf is enabled, and each of my wicket ajax requests
provides a 'x-xsrf-token' request header. Does this sound like a reasonable
solution? Are there any suggestions on improving this in some way?
Thank you again for your time.
Jonathan Babie
________________________________
From: Jonathan Babie
Sent: Monday, September 22, 2025 5:41 PM
To: Wicket User Group <[email protected]>
Subject: Spring Boot 3 & Wicket 10 CSRF Configuration Question
Hello,
We are working on a new application which is using Spring Security (Spring Boot
3.5.3) and Wicket (10.5.0), and we're encountering some issues with Spring CSRF:
Based on Wicket documentation for CSRFprevention, we have the following in our
WebApplication init():
```
setRootRequestMapper(new CryptoMapper(getRootRequestMapper(), this));
getRequestCycleListeners().add(new ResourceIsolationRequestCycleListener());
```
Then, on the side of Spring Security, we have CSRF enabled (default behavior).
With Spring CSRF enabled, all of our form ajax requests fail silently with a
403 forbidden error being logged in dev tools:
```
Request URL: http://localhost:8080/myapp/{encryptedurl}
Request Method: POST
Status Code: 403 Forbidden
Remote Address: [::1]:8080
Referrer Policy: strict-origin-when-cross-origin
```
My request headers contains a cookie with the XSRF-TOKEN, but this is not being
leveraged in any way currently.
If I disable Spring CSRF, everything works as expected.
Based on the research I've done for this, I need to essentially add an
'X-XSRF-TOKEN' request header which contains the value of my xsrf-token cookie
value but I couldn't find a Wicket hook to be able to do this and had a few
questions:
1.
Should we be enabling Spring CSRF in conjunction with Wicket's CSRF prevention
mechanism?
2.
If so, is there some hook to make these two work together seamlessly?
I was trying to address this via various listeners in my web application init,
but was unsuccessful.
We're hoping since Spring is such a popular framework, someone else has
experienced this / there's a clean solution. Please let me know if you need
anymore information and thank you for your time.
Thank you,
Jonathan Babie
Notice: This communication, including any attachments, is intended solely for
the use of the individual or entity to which it is addressed. This
communication may contain information that is protected from disclosure under
State and/or Federal law. Please notify the sender immediately if you have
received this communication in error and delete this email from your system. If
you are not the intended recipient, you are requested not to disclose, copy,
distribute or take any action in reliance on the contents of this information.