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:
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.
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.
If you like tutorials on this site, why not take a step further and connect me on Facebook , Google Plus & Twitter as well? I would love to hear your thoughts on these articles, it will help improve further our learning process.
In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…
Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…
Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…
Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…
Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…
This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…
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].
This is really helpful
Although the project is running but home page is not showing
Hi Satyam, what kind of problem are you facing? Have a look at Setup Tomcat+Eclipse for any deployment issue.
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?
Hi Abdul, probably your tomcat setup is not configured properly. Please have a look on Setup Tomcat With Eclipse, following the steps mentioned here should solve your issue.
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.
... which is smth that you seem to have not yet done :)
My bad, i missed it, will try to update it or provide a more advanced post to have it done.
Please try that one day :)
... better sooner than later :)