Code is extracted from my notice board example application, which uses Spring Security 5.6.7
CsrfFilter filter
CSRF protection is on by default when configuring HttpSecurity. A CsrfFilter is created and has the following function.
When the request method is not "GET", "HEAD", "TRACE" or "OPTIONS". To check if the provided CSRF matches record in the token registry. If not matched, a 403 forbidden response will be returned.
Otherwise, a SaveOnAccessCsrfToken is generated and saved as a HttpServletRequest attribute with name org.springframework.security.web.csrf.CsrfToken and _csrf. This token will not persist unless it is accessed by a template engine. When persistence it is done by HttpSessionCsrfTokenRepository instance and the token will be saved as a HttpSession attribute with name org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN.
Token access by thymeleaf engine
When rendering http form tag, such as
<form method="post" th:action="@{/loginHandler}" class="ui large form">
a hidden input tag will append afterward to provide CSRF token. In other word
<form method="post" action="/loginHandler" class="ui large form"><input type="hidden" name="_csrf" value="3c2ffa6d-ab75-41f3-ba10-7c423bf56071"/>
This is done by SpringActionTagProcessor. Then following method will be called to access CSRF token.
org.thymeleaf.spring5.requestdata.RequestDataValueProcessorUtils#getExtraHiddenFields
org.thymeleaf.spring5.context.webmvc.SpringWebMvcThymeleafRequestDataValueProcessor#getExtraHiddenFields
org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor#getExtraHiddenFields
@Override
public Map<String, String> getExtraHiddenFields(HttpServletRequest request) {
if (Boolean.TRUE.equals(request.getAttribute(this.DISABLE_CSRF_TOKEN_ATTR))) {
request.removeAttribute(this.DISABLE_CSRF_TOKEN_ATTR);
return Collections.emptyMap();
}
CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (token == null) {
return Collections.emptyMap();
}
Map<String, String> hiddenFields = new HashMap<>(1);
hiddenFields.put(token.getParameterName(), token.getToken());
return hiddenFields;
}
Top comments (0)