2016-11-26 76 views
0

我创建了以下LogoutSuccessHandlerImpl如何在弹簧安全性中注销用户后登录用户ID?

public class LogoutSuccessHandlerImpl extends SimpleUrlLogoutSuccessHandler { 

    private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); 

    @Override 
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { 
     final Long currentUserRoleId = SecurityUtils.getCurrentUserRoleId(); 

     request.getSession().invalidate(); 
     SecurityContextHolder.clearContext(); 

     request.setAttribute("isLoggedOut", "true"); 
     if(currentUserRoleId == UserRole.ADMIN.getId()){ 
      redirectStrategy.sendRedirect(request, response, Constants.ADMIN_LOGIN_URL); 
     } else { 
      redirectStrategy.sendRedirect(request, response, Constants.APPLICANT_LOGIN_URL); 
     } 
    } 
} 

以下是我的安全配置。

@Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      .exceptionHandling() 
       .accessDeniedPage("/accessDenied") 
       .and() 
      .authorizeRequests() 
       .accessDecisionManager(accessDecisionManager) 
       .antMatchers("/").permitAll() 
       .antMatchers("/application/register**").permitAll() 
       .antMatchers("/adminLogin**").permitAll() 
       .antMatchers("/error**").permitAll() 
       .antMatchers("/checkLogin**").permitAll() 
       .anyRequest().fullyAuthenticated() 
       .and() 
      .formLogin() 
       .loginPage("/") 
       .loginProcessingUrl("/checkLogin") 
       .defaultSuccessUrl("/dashboard") 
       .failureHandler(new LoginFailureHandlerImpl()) 
       .usernameParameter("username") 
       .passwordParameter("password") 
       .permitAll() 
       .and() 
      .logout() 
       .logoutUrl("/logout") 
       .logoutSuccessHandler(new LogoutSuccessHandlerImpl()) 
       .deleteCookies("JSESSIONID") 
       .permitAll() 
       .and() 
      .headers() 
       .frameOptions() 
       .disable() 
      .and() 
       .sessionManagement() 
       .maximumSessions(1); 
    } 

下面是我的SecurityUtils。

public static SecurityUser getCurrentUser() { 
     SecurityContext securityContext = SecurityContextHolder.getContext(); 
     Authentication authentication = securityContext.getAuthentication(); 
     if (authentication != null) { 
      if (authentication.getPrincipal() instanceof SecurityUser) { 
       return (SecurityUser) authentication.getPrincipal(); 
      } 
     } 
     throw new IllegalStateException("User not found!"); 
    } 

    public static Long getCurrentUserRoleId() { 
     return SecurityUtils.getCurrentUser().getRoleId(); 
    } 

和我得到的错误毕竟是LogoutHandler s的完成执行

java.lang.IllegalStateException: User not found! 
    at com.portal.core.user.security.SecurityUtils.getCurrentUser(SecurityUtils.java:34) 
    at com.portal.core.user.security.SecurityUtils.getCurrentUserRoleId(SecurityUtils.java:38) 
    at com.portal.core.user.security.LogoutSuccessHandlerImpl.onLogoutSuccess(LogoutSuccessHandlerImpl.java:22) 
+0

@ W-S如果if(authentication!= null)不满足。就在用户注销之前,身份验证不应该为空。所以异常不应该在那里。纠正我,如果我错了。 – ashishjmeshram

回答

0

LogoutSuccessHandler将被调用。这意味着在LogoutSuccessHandlerImpl.onLogoutSuccess中您的代码被调用时,SecurityContextHolder中不会有任何内容。这是因为SecurityContextLogoutHandler将被默认注册。 LogoutSuccessHandlerImpl中的以下行不起作用,因为它已由SecurityContextLogoutHandler完成。

SecurityContextHolder.clearContext(); 

您可以执行以下操作。

  1. 存储的用户ID和角色ID在HTTP会话
  2. 配置您的注销有logout().invalidateHttpSession(false)
  3. 修改您LogoutSuccessHandlerImpl.onLogoutSuccess从HttpSession中获取的用户ID和角色ID而不是SecurityContextHolder
0

authentication始终为null,因为在成功注销后调用LogoutSuccessHandler,请参阅LogoutSuccessHandler

LogoutFilter成功注销后调用的策略,用于处理重定向或转发到相应的目标。

您可以实现自定义LogoutHandler获得成功注销前用户的角色ID,请参阅LogoutHandler#logout

参数:

请求 - HTTP请求
响应 - 的HTTP回应
验证 - 当前主要细节

相关问题