用户在spring security中注销后如何获取登录用户ID?

时间:2016-11-26 04:12:00

标签: java spring spring-security

我创建了一个以下的LogoutSuccessHandlerImpl

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();
    }

我得到的错误是

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)

2 个答案:

答案 0 :(得分:0)

在所有LogoutSuccessHandler完成执行后,将调用

LogoutHandler。这意味着当LogoutSuccessHandlerImpl.onLogoutSuccess中没有任何内容时,将调用SecurityContextHolder中的您的代码。这是因为默认情况下会注册SecurityContextLogoutHandlerLogoutSuccessHandlerImpl中的以下行无效,因为SecurityContextLogoutHandler已完成。

SecurityContextHolder.clearContext(); 

您可以执行以下操作。

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

答案 1 :(得分:0)

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

  

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

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

  

<强>参数:

     

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