Spring Security exit does not work - the security context is not cleared and the authenticated user still exists

I know there are many articles on this topic, but I have a problem and I can not find a solution.

I have a classic spring java security code:

@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private AuctionAuthenticationProvider auctionAuthenticationProvider; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(auctionAuthenticationProvider); } @Override protected void configure(HttpSecurity http) throws Exception { http.httpBasic(); ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorizeRequest = http.authorizeRequests(); configureAdminPanelAccess(authorizeRequest); configureFrontApplicationAccess(authorizeRequest); configureCommonAccess(authorizeRequest); http.csrf() .csrfTokenRepository(csrfTokenRepository()).and() .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class); http.logout() .clearAuthentication(true) .invalidateHttpSession(true); } ... } 

In addition, I have two controller methods where I log in / log out of my AJAX web application.

When I want to log out, I first call this method, which I expect to clear user sessions and clear everything from the security context.

 @Override @RequestMapping(value = "/logout", method = GET, produces = APPLICATION_JSON_UTF8_VALUE) public ResponseEntity<Boolean> logout(final HttpServletRequest request, final HttpServletResponse response) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null){ new SecurityContextLogoutHandler().logout(request, response, auth); } return new ResponseEntity<>(Boolean.TRUE, HttpStatus.OK); } 

After that, I reload the client web application and every time it restarts, I check whether the user is authenticated by calling the following controller method:

 @Override @RequestMapping(value = "/user", method = GET, produces = APPLICATION_JSON_UTF8_VALUE) public ResponseEntity<UserDetails> user() { Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (principal instanceof UserDetails) { return new ResponseEntity<>((UserDetails) principal, HttpStatus.OK); } return null; } 

And here I get the last authenticated user. It seems that in the previous logout method, spring output does not work.

Keep in mind that I tried to log out with the following code without any success:

  @Override @RequestMapping(value = "/logout", method = GET, produces = APPLICATION_JSON_UTF8_VALUE) public ResponseEntity<Boolean> logout(final HttpServletRequest request) { try { request.logout(); return new ResponseEntity<>(Boolean.TRUE, HttpStatus.OK); } catch (ServletException ex) { if (LOG.isDebugEnabled()) { LOG.debug("There is a problem with the logout of the user", ex); } } 

Do you know what I missed in my configuration and during the logout process?

+5
java spring spring-mvc spring-security
source share
2 answers

From your question, I see that you are trying to create your own logout, and also trying to use spring logout by default. I advise you to choose one method that does not mix them both. There are two ways to show you should exit spring:

First: default spring security exit

 .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .logoutSuccessUrl("/logout.done").deleteCookies("JSESSIONID") .invalidateHttpSession(true) 

In the above example, you only need to call URL /logout when you want to log out. There is no need to create @Controller to handle this output; instead, spring will help log the user out of the system. You can also add another thing that you want to cancel here.

Second: a programmatic exit

 @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 use this output, you do not need to include the first method in the spring security configuration. Using this method, you can add additional actions to perform before and after logging off done.Btw, to use this logoff, just call the /logout URL and the user will log out manually. This method will invalidate the session, clear the spring security context and cookies.

Also, for the second method, if you use RequestMethod.POST , you need to include the csrf key as a message. An alternative way is to create a form with a csrf private input key. This is an example of using an automatic generated exit 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 the <a id="Logout">Logout</a> hyperlink to use it.

If you use RequestMethod.GET , just include the csrf key as a parameter in your link, for example:

 <a href="${pageContext.request.contextPath}/logout?${_csrf.parameterName}=${_csrf.token}">Logout</a> 

That's all, I hope, his help.

+18
source share

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() 
0
source share

All Articles