Spring Security Logout Success Handler Example
- Details
- Written by Nam Ha Minh
- Last Updated on 30 October 2020   |   Print Email
In this Spring Security post, you will learn how to write code to perform custom logics when a user has just logged out from a Spring Boot application. In practice, we may need to customize the default logout process of Spring Security to the following tasks:
- Log the logged-out user (for auditing purpose)
- Display different logout success pages based on user’s roles
- Clean up resources that are used temporarily by the user
- Any custom logics upon successful logout
Spring Security allows programmers to intervene the logout process by configuring a Logout success handler. The following diagram helps you understand the use of a Logout success handler in the context of Spring Security:
As you can see, when a user has logged out successfully, Spring Security will call the Logout Success Handler and execute its callback method. And in this handler, after performing the custom logics, you can decide to redirect the user to the default logout success page, or any page you want to user to see.
1. Simple Logout Success Handler Example
The simplest way to use a logout success handler is create an anonymous class of type LogoutSuccessHandler as argument to the method logoutSuccessHandler() of the LogoutConfigurer class, as shown below:
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { ... @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() ... .formLogin() .loginPage("/login") .usernameParameter("email") .permitAll() .and() .logout() .logoutSuccessHandler(new LogoutSuccessHandler() { @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { CustomerUserDetails userDetails = (CustomerUserDetails) authentication.getPrincipal(); String username = userDetails.getUsername(); System.out.println("The user " + username + " has logged out."); response.sendRedirect(request.getContextPath()); } }) .permitAll(); ... } }
As you can see, the onLogoutSuccess() method will be invoked by Spring Security upon successful logout of a user. In this example, we just get username of the logged-out user and print it to the standard output, and redirect the user to the application’s context path.
It’s recommended to use a subtype of LogoutSuccessHandler like SimpleUrlLogoutSuccessHandler which handles the navigation on logout automatically. For example:
.logout() .logoutSuccessHandler(new SimpleUrlLogoutSuccessHandler() { @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { CustomerUserDetails userDetails = (CustomerUserDetails) authentication.getPrincipal(); String username = userDetails.getUsername(); System.out.println("The user " + username + " has logged out."); super.onLogoutSuccess(request, response, authentication); } }) .permitAll()
Spring Security also provides the HttpStatusReturningLogoutSuccessHandler which returns an HTTP status code instead of redirection, which is useful for RESTful webservices.
2. Advanced Logout Success Handler Example
In case the Logout success handler needs to depend on a business/service class to perform the custom logics, we need to create a separate class as follows:
@Component public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler { @Autowired private CustomerServices customerService; @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { CustomerUserDetails userDetails = (CustomerUserDetails) authentication.getPrincipal(); String username = userDetails.getUsername(); Customer customer = customerService.getCustomerByEmail(username); // process logics with customer super.onLogoutSuccess(request, response, authentication); } }
Here, the @Component annotation tells Spring framework to manage instances of this class as beans. And the @Autowired annotation tells Spring framework to inject an instance of the business class into this handler class.
Then configure the Spring Security configuration class like this:
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { ... @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() ... .formLogin() .loginPage("/login") .usernameParameter("email") .permitAll() .and() .logout() .logoutSuccessHandler(logoutSuccessHandler) .permitAll(); ... } @Autowired private CustomLogoutSuccessHandler logoutSuccessHandler; }
That’s some examples about logout success handler in Spring Boot. To see the coding in action, I recommend you to watch the following video:
Related Spring Security Tutorials:
- Spring Security Authentication with JPA, Hibernate and MySQL
- Spring Security Role-based Authorization Tutorial
- Spring Security Customize Login and Logout
- How to Get Logged-in User's Details with Spring Security
- Spring Security: Prevent User from Going Back to Login Page if Already logged in
- Spring Security Authentication Success Handler Examples
- Spring Security Authentication Failure Handler Examples
- Spring Security Before Authentication Filter Examples
Other Spring Boot Tutorials:
- How to create a Spring Boot Web Application (Spring MVC with JSP/ThymeLeaf)
- Spring Boot CRUD Example with Spring MVC – Spring Data JPA – ThymeLeaf - Hibernate - MySQL
- Spring Boot Hello World RESTful Web Services Tutorial
- Spring Boot Thymeleaf Form Handling Tutorial
- Spring Data JPA Paging and Sorting Examples
- Spring Boot Error Handling Guide
- Spring Boot Logging Basics
Comments