We currently have a problem with the Spring CSRF solution for our legacy application, because the CSRF implementation changes the default behavior of Spring security Spring sis security configuration:
<http pattern=""> ... <logout logout-url="/logout" delete-cookies="..." success-handler-ref="logoutSuccessHandler" /> <csrf/> </http>
org.springframework.security.config.annotation.web.configurers.LogoutConfigurer The output configurator. According to the Spring documentation:
Adding CSRF will update LogoutFilter only to use HTTP POST. This ensures that a CSRF token is required to exit the system and that an attacker cannot force users to log out of the system.
The code that makes this change is as follows:
private RequestMatcher getLogoutRequestMatcher(H http) { if(logoutRequestMatcher != null) { return logoutRequestMatcher; } if(http.getConfigurer(CsrfConfigurer.class) != null) { this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST"); } else { this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl); } return this.logoutRequestMatcher; }
Typically, this behavior makes sense to protect CSRF. But it’s very strange for me that this implementation is not flexible (why are hard variables of real implementations, not autowire dependencies?).
The problem is that our application is built in such a way that before performing a regular Spring exit, it performs additional cleanup in the Spring controllers. Basically, the Switch User function is implemented, but in its own way. Thus, changing the logout path to perform POST is not an option, because basically the cleanup is done on the user controller.
There seems to be only one possible solution to use this approach:
@RequestMapping(value = "/logout", method = RequestMethod.GET) //or it can be a post public String logout() { // 1. Perform Clean up // 2. Decide whether to logout or redirect to other page // 3. Perform redirect based on decision }
// If he decided to log out, this will go to this controller method:
@RequestMapping(value = "csrflogout", method = RequestMethod.GET) public void csrfLogout(){
Typically, this approach is not good in terms of code quality. So there are two questions:
- What is the reason for such a strict implementation in Spring and does not give a visible opportunity to override it (in particular, I gave an example of the code how it was created)?
- Any good alternative to fix the mentioned problem.