NullPointerException on expired session

David Antelo :

I'm using Spring, and I need to expire the session of a user when I update said user. I'm using the following configuration:

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

}

And this is how I expire sessions:

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

When this is done, and I reload the page on the browser where I had my updated user, it will show the Exception:

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

Which redirects to:

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

In particular, it's the last line of code the one throwing the exception. If I reload the page again, after getting the exception, then everything is fine; I get no exception and I'm logged out. I have no idea why this is happening. Does anybody know?

David Antelo :

Ok, I finally managed to solve this problem. The answer is to use your own ConcurrentSessionFilter, since many of the methods used by the default one are deprecated. Add this bean:

 @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;

}

And do whatever you want in the overwritten method, in my case I used my new RedirectStrategy to move users to the index page.

And then add this to your config method:

protected void configure (HttpSecurity http) throws Exception {

    ...
    // Whatever you want to configure

    http.addFilterBefore(concurrentSessionFilter(), ConcurrentSessionFilter.class);

}

I can't believe how unintuitive this was, I don't know how such a simple thing as expiring sessions can be so hard and obtuse in Spring

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=131403&siteId=1