Spring 4 Security Custom LogoutSuccessHandler Example

By Arvind Rai, March 27, 2016
On this page we will provide spring 4 security custom LogoutSuccessHandler example. The responsibility of LogoutSuccessHandler is to redirect or forward the page to desired location after successful logout. Once we configure LogoutSuccessHandler using http.logoutSuccessHandler() in our security configuration, it takes precedence over http.logoutSuccessUrl() if configured. Custom LogoutSuccessHandler is useful where we need to perform some task after successful logout. It is also useful to forward the page only with HTTP status code in header useful in REST web service.

LogoutSuccessHandler

LogoutSuccessHandler is called after successful logout in our spring security application. The responsibility of this class is to redirect or forward to required destination with appropriate HttpStatus. To use LogoutSuccessHandler implementation classes, we need to pass its instance to http.logoutSuccessHandler() method.
http.logout().    
logoutUrl("/appLogout").
http.logoutSuccessHandler(myLogoutSuccessHandler); 
//.logoutSuccessUrl("/app"); 
Once we configure http.logoutSuccessHandler(), it takes precedence over http.logoutSuccessUrl() configuration. LogoutSuccessHandler has two implementations.

SimpleUrlLogoutSuccessHandler : It handles the navigation on successful logout. We use it as follows.
http.logout().    
logoutUrl("/appLogout").
logoutSuccessHandler(new SimpleUrlLogoutSuccessHandler()); 


HttpStatusReturningLogoutSuccessHandler : It has been introduced in spring web security 4. It sends only HTTP status code in response header. It is useful where there is no redirection required after successful logout such as REST web service. We can set required HTTP status code passing as constructor argument, by default it sends HttpStatus.OK.
http.logout().    
logoutUrl("/appLogout").
logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler(HttpStatus.ACCEPTED)); 

Custom LogoutSuccessHandler

For custom LogoutSuccessHandler, we need to create a class implementing LogoutSuccessHandler interface and override onLogoutSuccess() method that can throw exception unlike LogoutHandler.logout(). Using custom LogoutSuccessHandler, we can perform any task which is needed after successful logout. Here we can redirect the page to required destination with required HTTP status code.
MyLogoutSuccessHandlerOne.java
package com.concretepage.handler;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
@Component
public class MyLogoutSuccessHandlerOne implements LogoutSuccessHandler {
	@Override
	public void onLogoutSuccess(HttpServletRequest request,
			HttpServletResponse response, Authentication authentication)
			throws IOException, ServletException {
		if(authentication != null) {
			System.out.println(authentication.getName());
		}
		//perform other required operation
		String URL = request.getContextPath() + "/app";
		response.setStatus(HttpStatus.OK.value());
		response.sendRedirect(URL);
	}
} 
We will get the output page as follows.
Spring 4 Security Custom LogoutSuccessHandler Example
In the scenario where redirection is not required, we can just send required HTTP status code.
MyLogoutSuccessHandlerTwo.java
package com.concretepage.handler;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
@Component
public class MyLogoutSuccessHandlerTwo implements LogoutSuccessHandler {
	@Override
	public void onLogoutSuccess(HttpServletRequest request,
			HttpServletResponse response, Authentication authentication)
			throws IOException, ServletException {
		if(authentication != null) {
			System.out.println(authentication.getName());
		}
		//perform other required operation		
		response.setStatus(HttpStatus.OK.value());
		response.getWriter().flush();
	}
} 
Find the response header print screen
Spring 4 Security Custom LogoutSuccessHandler Example
Find the JavaConfig for security configuration used in our example.
SecurityConfig.java
package com.concretepage.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import com.concretepage.handler.MyLogoutSuccessHandlerOne;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	@Autowired
	private MyLogoutSuccessHandlerOne myLogoutSuccessHandler;
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		//authorize requests		
		http.authorizeRequests().
		antMatchers("/app/secure/**").
		access("hasRole('ROLE_ADMIN')");
		
		//login configuration
		http.formLogin().  
                loginPage("/app").
                loginProcessingUrl("/appLogin").
                usernameParameter("app_username").
                passwordParameter("app_password").
                defaultSuccessUrl("/app/secure/home");
		
		//logout configuration
                http.logout().    
		logoutUrl("/appLogout").
		logoutSuccessHandler(myLogoutSuccessHandler); 
	} 
	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
		auth.inMemoryAuthentication().withUser("ram").password("ram123").roles("ADMIN");
	}	
} 

Software Used

Find the software used in our demo.
1. Java 8
2. Spring-Security 4.0.3.RELEASE
3. Tomcat 8
4. Gradle
5. Eclipse

Gradle File

build.gradle
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'war'
archivesBaseName = 'spring4javaconfig'
version = '1' 
repositories {
    mavenCentral()
}
dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web:1.3.3.RELEASE'
    compile 'org.springframework.boot:spring-boot-starter-security:1.3.3.RELEASE'
    compile 'jstl:jstl:1.2'     
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat:1.3.3.RELEASE'    
} 

Other Java Files and Views used in Example

AppConfig.java
package com.concretepage.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@ComponentScan("com.concretepage")
@Import(SecurityConfig.class)
@EnableWebMvc
public class AppConfig {
    @Bean  
    public InternalResourceViewResolver viewResolver() {  
	InternalResourceViewResolver resolver = new InternalResourceViewResolver();  
        resolver.setPrefix("/WEB-INF/secure/");  
        resolver.setSuffix(".jsp");
        return resolver;  
    }	
} 
SecurityInitializer.java
package com.concretepage.config;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
} 
WebAppInitializer.java
package com.concretepage.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[] { AppConfig.class };
	}
	@Override
	protected Class<?>[] getServletConfigClasses() {
		return null;
	}
	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}
} 
StudentController.java
package com.concretepage.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.concretepage.bean.Student;
@Controller
@RequestMapping("/app")
public class StudentController {
	@RequestMapping
	public String login() {
 		return "customLogin";
 	} 	
	@RequestMapping("/secure/home")
	public String homePage(Model model) {
		List<Student> list = new ArrayList<>();
		list.add(new Student(1, "Shankar"));
		list.add(new Student(2, "Vishnu"));
		list.add(new Student(3, "Bhahma"));
		model.addAttribute("list", list);
 		return "home";
 	}    
} 
Student.java
package com.concretepage.bean;
public class Student {
	private int stdId;
	private String stdName;
	public Student(int stdId, String stdName) {
		this.stdId = stdId;
		this.stdName = stdName;
	}
	public int getStdId() {
		return stdId;
	}
	public void setStdId(int stdId) {
		this.stdId = stdId;
	}
	public String getStdName() {
		return stdName;
	}
	public void setStdName(String stdName) {
		this.stdName = stdName;
	}
} 
customLogin.jsp
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
    <head>
        <title>Spring Security Example</title>
    </head>
    <body>
       <h3>Spring Security Example</h3>
        <font color="red">
		   ${SPRING_SECURITY_LAST_EXCEPTION.message}
        </font>
	<form:form action="${pageContext.request.contextPath}/appLogin" method="POST">
		Enter UserName:	<input type="text" name="app_username"/><br/><br/>
		Enter Password: <input type="password" name="app_password"/> <br/><br/>		
		<input type="submit" value="Login"/>
	</form:form>
    <body>
</html> 
home.jsp
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
    <head>
        <title>Spring Security Example</title>
    </head>
    <body>
        <form:form action="${pageContext.request.contextPath}/appLogout" method="POST">
           <input type="submit" value="Logout"/>
        </form:form>   
        Welcome to you. Find secure data. <br/>
	<c:forEach var="ob" items="${list}">
	    <br/><c:out value="${ob.stdId}"></c:out>
	      <c:out value="${ob.stdName}"></c:out>	        
	</c:forEach>
    </body>
</html> 
To run application, use URL http://localhost:8080/spring4javaconfig-1/app

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us