Categories: spring-security

Spring Security 4 Logout Example

This post shows you how to programatically logout a user in Spring Security. This works well with browser back button too. Let’s get going.


Generally, In your views, you should be providing a simple logout link to logout a user, something like shown below:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <title>Admin page</title>
</head>
<body>
 Dear <strong>${user}</strong>, Welcome to Admin Page.
 <a href="<c:url value="/logout" />">Logout</a>
</body>
</html>

Nothing fancy about it. Now , We just need to map this /logout link in our controller. Create a new method like shown below:

 @RequestMapping(value="/logout", method = RequestMethod.GET)
 public String logoutPage (HttpServletRequest request, HttpServletResponse response) {
  Authentication auth = SecurityContextHolder.getContext().getAuthentication();
  if (auth != null){    
   new SecurityContextLogoutHandler().logout(request, response, auth);
  }
  return "redirect:/login?logout";//You can redirect wherever you want, but generally it's a good practice to show login screen again.
 }

Here firstly we identified if user was authenticated before using SecurityContextHolder.getContext().getAuthentication(). If he/she was, then we called SecurityContextLogoutHandler().logout(request, response, auth) to logout user properly.

This logout call performs following:

  • Invalidates HTTP Session ,then unbinds any objects bound to it.
  • Removes the Authentication from the SecurityContext to prevent issues with concurrent requests.
  • Explicitly clears the context value from the current thread.

That’s it. You don’t need anything else anywhere in your application to handle logout. Notice that you don’t even need to do anything special in your spring configuration(xml or annotation based), shown below just for information:

package com.websystique.springsecurity.configuration;

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;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

 
 @Autowired
 public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
  auth.inMemoryAuthentication().withUser("bill").password("abc123").roles("USER");
  auth.inMemoryAuthentication().withUser("admin").password("root123").roles("ADMIN");
  auth.inMemoryAuthentication().withUser("dba").password("root123").roles("ADMIN","DBA");
 }
 
 @Override
 protected void configure(HttpSecurity http) throws Exception {
   
   http.authorizeRequests()
    .antMatchers("/", "/home").permitAll()
    .antMatchers("/admin/**").access("hasRole('ADMIN')")
    .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
    .and().formLogin().loginPage("/login")
    .usernameParameter("ssoId").passwordParameter("password")
    .and().exceptionHandling().accessDeniedPage("/Access_Denied");
 }
}

There is no special logout handling mentioned in above configuration.

Above security configuration in XML configuration format would be:

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">
     
    <http auto-config="true" >
        <intercept-url pattern="/" access="hasRole('USER')" />
        <intercept-url pattern="/home" access="hasRole('USER')" />
        <intercept-url pattern="/admin**" access="hasRole('ADMIN')" />
        <intercept-url pattern="/dba**" access="hasRole('ADMIN') and hasRole('DBA')" />
        <form-login  login-page="/login" 
                     username-parameter="ssoId" 
                     password-parameter="password" 
                     authentication-failure-url="/Access_Denied" />
    </http>
 
    <authentication-manager >
        <authentication-provider>
            <user-service>
                <user name="bill"  password="abc123"  authorities="ROLE_USER" />
                <user name="admin" password="root123" authorities="ROLE_ADMIN" />
                <user name="dba"   password="root123" authorities="ROLE_ADMIN,ROLE_DBA" />
            </user-service>
        </authentication-provider>
    </authentication-manager>
    
</beans:beans>

Rest of application code is same as mentioned in every post in this series. This Post (and actually every post in this series) shows this logout in action.

Deploy & Run

Download complete code of this project using download button shown at the bottom of this post. Build and deploy it on Servlet 3.0 container(Tomcat7/8).

Open your browser, go to http://localhost:8080/SpringSecurityCustomLogoutExample/, home page will be shown

Now go to http://localhost:8080/SpringSecurityCustomLogoutExample/admin, you will be prompted for login

provide credentials, submit, you will see admin page.

click on logout, you will be taken to login page.

click on browser back button, you will remain at login screen.

That’s it. Next post shows you how to show/hide parts of jsp/view based on logged-in user’s roles, using Spring Security tags.

Download Source Code


References

View Comments

  • Hi, thanks for the tutorial..
    You wrote pattern="/dba**" instead of "/db**" in the security configuration xml file

  • am getting error

    type Status report

    message Request method 'POST' not supported

    description The specified HTTP method is not allowed for the requested resource.

    Apache Tomcat/7.0.47

    after login as admin

    user name : admin
    password : root123

    • Hello Krish, do you have more logs of this issue. Can you still reproduce it? May i ask you to add
      on header part of JSP and see if you can reproduce the problem?

      • It's working error because of not added ...I found later an hour this from another blog .. And now it's working ... Thanks for ur reply.

  • Can you please point me out what is 'param' in the following snippet of the login.jsp after redirection on logout:
    You have been logged out successfully.

    • param refers to query parameter. Here we are saying that if the query parameter logout exists, means the user has been logged out [you won't have this param if the user is not yet logged out].

  • So the point of this article is to give details to the previous tutorial while the code is exactly the same?

    • Right. Although there are different opinions; Many a times i was asked by fellow Readers to include everything to make the post independent, and other times, i had to decide to keep it short if most of the stuff is similar to an existing post.

  • Hi Thank you for the great tutorials, these are really helpful.

    I have downloaded the code for this particular example , then did the following steps
    1. Ran mvn dependency:copy-dependencies in the project folder
    2. Imported the project into eclipse
    3. Ran Maven update
    4. Converted project to dynamic web project using the project facets and specifying the webcontent folder as src/main/webapp
    5. Ran the application on tomcat 7, jdk 1.7.0_91, but the application gave 404 error when loading the home page.

    Could you please let me know how do i run the downloaded code?

      • Thank you for your swift response. As of now, i am using mvn clean install and then deploying the war manually on to the tomcat server using the tomcat manager gui.

        My eclipse embedded tomcat setup is correct as i am able to run other web apps using eclipse.

        I actually never used maven, but can you tell me after i download, how do i import this to eclipse as a WEB APP and then run it using eclipse, run as -> run on server... .

        Any help/pointers would be really helpful.

        Thank you in advance. :)

  • This should be updated to include functionality to remove rememberMe cookies that will cause the user to be re-authenticated regardless of the session-invalidating/SecurityContextHolder emptying process that the `SecurityContextLogoutHandler.logout(...)` call induces; see http://stackoverflow.com/questions/5727380/how-to-manually-log-out-a-user-with-spring-security :

    you need to add a call to CookieClearingLogoutHandler.logout(...) with a cookieClearingLogoutHandler initialized with AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY

    • Hi,
      Thanks for pointing it out. You are absolutely right. Even if we are not discussing about cookie in this particular post, we should include the cookie removal logic to perform a clean logout. I will update the post. Thanks again.

Share
Published by

Recent Posts

Spring Boot + AngularJS + Spring Data + JPA CRUD App Example

In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…

8 years ago

Spring Boot Rest API Example

Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…

8 years ago

Spring Boot WAR deployment example

Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…

8 years ago

Spring Boot Introduction + hello world example

Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…

8 years ago

Secure Spring REST API using OAuth2

Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…

8 years ago

AngularJS+Spring Security using Basic Authentication

This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…

8 years ago