Search code examples
javaspringspring-bootjavabeans

Spring boot sessionRegistry returns empty list of principals


I'm using spring security in my spring boot app to provide user functionality. I've spent quiet some time searching for an answer to the problem, but did only find solutions for people using xml-based configurations.

My set-up is very similar to this: http://www.baeldung.com/spring-security-track-logged-in-users (alternative method at the bottom).

This is my SecurityConfiguration:

@Override
    protected void configure(HttpSecurity http) throws Exception {

    http.formLogin().defaultSuccessUrl("/home.html", true)
    //.and().exceptionHandling().accessDeniedPage("/home")
    .and().authorizeRequests().antMatchers("/editor").hasAnyAuthority("SUPERUSER")
    .and().authorizeRequests().antMatchers("/editor").hasAnyAuthority("ADMIN")
    .and().authorizeRequests().antMatchers("/").permitAll().anyRequest().authenticated()
    .and().formLogin().loginPage("/login").permitAll()
    .and().authorizeRequests().antMatchers("/static/**").permitAll()
    .and().logout().permitAll().logoutSuccessUrl("/login").logoutUrl("/logout").deleteCookies("JSESSIONID")
    .and().csrf().disable();

    http.sessionManagement().invalidSessionUrl("/login").maximumSessions(1).sessionRegistry(sessionRegistry()).expiredUrl("/login");


}

This is where i call the sessionRegistry:

public List<String> getAllLoggedUsernames() {

    final List<Object> allPrincipals = sessionRegistry.getAllPrincipals();
    // System.out.println("All Principals: " + sessionRegistry.getAllPrincipals());
    List<String> allUsernames = new ArrayList<String>();
    System.out.println(allUsernames.size());
    for (final Object principal : allPrincipals) {

        if (principal instanceof SecUserDetails) {
            final SecUserDetails user = (SecUserDetails) principal;

            //Make sure the session is not expired --------------------------------------------------▼ 
            List<SessionInformation> activeUserSessions = sessionRegistry.getAllSessions(principal, false);
            if (!activeUserSessions.isEmpty()) {
                allUsernames.add(user.getUsername());
                System.out.println(user.getUsername());
            }

        }
    }

    return allUsernames;
}

Now when I try to get the currently logged-in user i get it correctly like that:

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    String username = auth.getName();

My sessionRegistry is defined as a Bean the following way:

@Bean
public SessionRegistry sessionRegistry() {
    return new SessionRegistryImpl();

}

It is left to say that I call the getAllLoggedUsernames() from a controller via a service much like this:

@Autowired
private SecUserDetailService service;

And later in a @RequestMapping function:

service.getAllLoggedUsernames();

And the list received there is always empty, no matter how many users are actually logged in.

Now my guess from other questions asked here would be that somehow my application gets loaded twice or that my bean setup is messed up. I kind of think that the @Autowired does not work, since I think the Service needs some kind of context information?

I'm really new to Dependency injection though, so it's kinda hard to get everything correct.

Thanks for any help in advance!

Edit - Minor clarifications


Solution

  • Solved: There was a type error, the if statement in the getAllLoggedUsers() method always resolved to false as the Object is not an instance of my own UserDetails class, but of org.springframework.security.core.userdetails.User!