Spring Security logout does not work - does not clear security context and authenticated user still exists
From your question,I see you are trying to create your own logout and you also trying to use the default spring logout.I advise you should choose one method only not mixed them both.There are two way I can show you to logout from spring:
First: Default spring security logout
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/logout.done").deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
From example above, you should only need to call the /logout
url whenever you want to logout the user. No need to create any @Controller
to handle that logout instead spring will help to log the user out. You also can add other thing you want to invalidate here.
Second: Proggrammatically logout
@RequestMapping(value = {"/logout"}, method = RequestMethod.POST)
public String logoutDo(HttpServletRequest request,HttpServletResponse response){
HttpSession session= request.getSession(false);
SecurityContextHolder.clearContext();
session= request.getSession(false);
if(session != null) {
session.invalidate();
}
for(Cookie cookie : request.getCookies()) {
cookie.setMaxAge(0);
}
return "logout";
}
If you are using this logout,you doesn't need to include the first method in spring security config. By using this method,you can add extra action to do before and after logout done.Btw, to use this logout ,just call the /logout
url and user will be logout manually.This method will invalidate session,clear spring security context and cookies.
In addition for second method, if you are using RequestMethod.POST
, you need to include the csrf key as a post. The alternative way is to create a form with hidden input csrf key. This is some example of auto generated logout link with jquery :
$("#Logout").click(function(){
$form=$("<form>").attr({"action":"${pageContext.request.contextPath}"+"/logout","method":"post"})
.append($("<input>").attr({"type":"hidden","name":"${_csrf.parameterName}","value":"${_csrf.token}"}))
$("#Logout").append($form);
$form.submit();
});
You just need to create hyperlink <a id="Logout">Logout</a>
to use it.
If you are using RequestMethod.GET
,just include a csrf key as a parameter in you link like this:
<a href="${pageContext.request.contextPath}/logout?${_csrf.parameterName}=${_csrf.token}">Logout</a>
Thats all,hope its help.
This will help, i think clearAuthentication(true) is enough:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
....
@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.httpBasic()
.and()
.logout().clearAuthentication(true)
.logoutSuccessUrl("/")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.and()
Just a heads up, there is Clear Site Data HTTP header as shown below
Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
I also helped add support for Clear-Site-Data
header into Spring-Security 5.2
project. For more details around the implementation, see the PR.
Here is a sample of how it is going to work
@EnableWebSecurity
static class HttpLogoutConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.addLogoutHandler(new HeaderWriterLogoutHandler(
new ClearSiteDataHeaderWriter(SOURCE)));
}
}
Where SOURCE is a vararg
of one or more of the following
"*"
Clear everything- One or more of
"cache", "cookies", "storage", "executionContexts"
For more details see the sample test in the LogoutConfigurerClearSiteDataTests.java.