Skip to content

Genereate csrf token error in concurrent environment #5219

@someoneYYYY

Description

@someoneYYYY

Summary

We use spring-security csrf token mechanism to generate csrf token , but occurs some error in concurrent environment , we get csrf token by this way

 CsrfToken token = (CsrfToken)request.getAttribute(CsrfToken.class.getName());
 String sessionId = RequestContextHolder.currentRequestAttributes().getSessionId();
 CsrfTokenDTO csrfTokenDTO = new CsrfTokenDTO();
 csrfTokenDTO.setSessionId(sessionId);
 csrfTokenDTO.setCsrfToken(token.getToken());

If we send two requests at same time ,we will get two csrf token response from server, but the first return csrf token is invalid, in other word, one session have two csrf token, one of them is invalid. just like below

{"csrfToken":"7e5fc5e2-084e-4042-bed4-d133fe910d26","sessionId":"341AB97535817BF0D04507E65FC9CCA7","description":"Please add Header 'X-CSRF-TOKEN', and cookie '' for all Post request","sessionName":""}
{"csrfToken":"7e5fc5e2-7552e-4042-bed4-d133fe910d26","sessionId":"341AB97535817BF0D04507E65FC9CCA7","description":"Please add Header 'X-CSRF-TOKEN', and cookie '' for all Post request","sessionName":""}

we thought this behavior cause by this reason , there is no have synchronized in CsrfFilter

@Override
	protected void doFilterInternal(HttpServletRequest request,
			HttpServletResponse response, FilterChain filterChain)
					throws ServletException, IOException {
		request.setAttribute(HttpServletResponse.class.getName(), response);
               // need add synchronized avoid generate two csrf token
		CsrfToken csrfToken = this.tokenRepository.loadToken(request);
		final boolean missingToken = csrfToken == null;
		if (missingToken) {
			csrfToken = this.tokenRepository.generateToken(request);
			this.tokenRepository.saveToken(csrfToken, request, response);
		}
		request.setAttribute(CsrfToken.class.getName(), csrfToken);
		request.setAttribute(csrfToken.getParameterName(), csrfToken);

		if (!this.requireCsrfProtectionMatcher.matches(request)) {
			filterChain.doFilter(request, response);
			return;
		}
}

Actual Behavior

A session corresponds to two csrf token

Expected Behavior

A session corresponds to a csrf token

Configuration

we use csrf mechanism by this way

 http.authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .addFilterBefore(multiAuthenticationFilter,UsernamePasswordAuthenticationFilter.class)
            .csrf().ignoringAntMatchers(SecurityConfigConstant.IGNORE_CSRF_PATH.toArray(new String[0]))
            .and()
            .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);

Version

4.23.RELEASE

Metadata

Metadata

Assignees

Labels

status: declinedA suggestion or change that we don't feel we should currently apply

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions