过期会话上的空指针异常



我正在使用Spring,当我更新该用户时,我需要使该用户的会话过期。我使用以下配置:

@Bean
@Override
public AuthenticationManager authenticationManagerBean () throws Exception {
    return super.authenticationManagerBean();
}
@Bean
public SessionRegistry sessionRegistry () {
    return new SessionRegistryImpl();
}
@Bean
public ServletListenerRegistrationBean httpSessionEventPublisher() {    //(5)
    return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
}
@Override
public void configure(AuthenticationManagerBuilder authenticationMgr) throws Exception {
    authenticationMgr.userDetailsService(inMemoryUserDetailsManager());
}
@Override
protected void configure (HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("*.jsp").authenticated()
        .and()
            .formLogin().loginPage("/login.html")
            .defaultSuccessUrl("/")
            .failureUrl("/login.html?failed=1")
            .usernameParameter("email").passwordParameter("password")               
        .and()
            .logout().logoutUrl("/logout.html")
        .and()
            .logout().logoutSuccessUrl("/")
        .and()
            .sessionManagement()
            .maximumSessions(100)
            .maxSessionsPreventsLogin(true)
            .expiredUrl("/ejercicios-programacion/")
            .sessionRegistry(sessionRegistry());
}

这就是我使会话过期的方式:

public void expireUserSessions(String username) {
    for (Object principal : sessionRegistry.getAllPrincipals()) {
        if (principal instanceof User) {
            UserDetails userDetails = (UserDetails) principal;
            if (userDetails.getUsername().equals(username)) {
                for (SessionInformation information : sessionRegistry.getAllSessions(userDetails, false)) {
                    information.expireNow();
                }
            }
        }
    }
}

完成此操作后,我在更新用户的浏览器上重新加载页面,它将显示异常:

java.lang.NullPointerException
org.springframework.security.web.session.ConcurrentSessionFilter$1.onExpiredSessionDetected(ConcurrentSessionFilter.java:107)

重定向至:

@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
    HttpServletRequest request = event.getRequest();
    HttpServletResponse response = event.getResponse();
    SessionInformation info = event.getSessionInformation();
    redirectStrategy.sendRedirect(request, response, determineExpiredUrl(request, info));
}

特别是,它是引发异常的最后一行代码。如果我在收到异常后再次重新加载页面,那么一切都很好;我没有例外,我已注销。我不知道为什么会这样。有人知道吗?

好的,我终于设法解决了这个问题。答案是使用您自己的ConcurrentSessionFilter,因为默认方法使用的许多方法都被弃用了。添加此豆子:

 @Bean public ConcurrentSessionFilter concurrentSessionFilter() {
    ConcurrentSessionFilter c = new ConcurrentSessionFilter(sessionRegistry(), new SessionInformationExpiredStrategy() {
        @Override
        public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
            HttpServletRequest request = event.getRequest();
            HttpServletResponse response = event.getResponse();
            SessionInformation info = event.getSessionInformation();
            redirectStrategy().sendRedirect(request, response, "/ejercicios-programacion/");
        }
    });
    return c;
}

并在覆盖方法中做任何您想做的事情,就我而言,我使用我的新重定向策略将用户移动到索引页面。

然后将其添加到您的配置方法中:

protected void configure (HttpSecurity http) throws Exception {
    ...
    // Whatever you want to configure
    http.addFilterBefore(concurrentSessionFilter(), ConcurrentSessionFilter.class);
}

我简直不敢相信这是多么不直观,我不知道像过期会议这样简单的事情在春天怎么会如此困难和迟钝

最新更新