SpringBoot 2.7.18, responding spring-security starter. The authentication is worked well, but the concurrent max session control is not worked. I knew that I need invoke onAuthentication() by manul, but It seems that some steps are missing. My SecurityConfig:

@EnableMethodSecurity
@SpringBootConfiguration
public class SecurityConfig {
    @Bean
    SessionRegistry sessionRegistry()
    {
        return new SessionRegistryImpl();
    }
    @Bean
    ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlAuthenticationStrategy(SessionRegistry sessionRegistry)
    {
        ConcurrentSessionControlAuthenticationStrategy cs=new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry);
        cs.setMaximumSessions(1);
        return cs;
    }
    @Bean
    PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager(
            GSUserDetailedsService userDetailsService,
            PasswordEncoder passwordEncoder) {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService);
        authenticationProvider.setPasswordEncoder(passwordEncoder);

        return new ProviderManager(authenticationProvider);
    }

    @Bean
    RoleHierarchy hierarchyVoter() {
        RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
        hierarchy.setHierarchy("ROLE_ADMIN > ROLE_ZHUXI\n ROLE_ZHUXI > ROLE_WEIY");
        return hierarchy;
    }

    @Bean
    MethodSecurityExpressionHandler methodSecurityExpressionHandler(RoleHierarchy roleHierarchy) {
        DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setRoleHierarchy(roleHierarchy);
        return expressionHandler;
    }

    @Bean
    HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }

    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.formLogin(login -> login.loginPage("/index.html"))
                .authorizeRequests(requests -> requests.antMatchers("/index.html", "/login-post", "/assets/**")
                        .permitAll().anyRequest().authenticated())
                .csrf(csrf -> csrf.ignoringAntMatchers("/login-post"));
        return http.build();
    }

}

My LoginController: ```@RestController public class LoginController {

private final AuthenticationManager authenticationManager;

private final SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder.getContextHolderStrategy();
private SecurityContextRepository securityContextRepository = new HttpSessionSecurityContextRepository();
private SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler();

@Autowired
private ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlAuthenticationStrategy;

public LoginController(AuthenticationManager authenticationManager) {
    this.authenticationManager = authenticationManager;
}

@PostMapping("/login-post")
public void login(@RequestBody UserInfoDTO loginRequest, HttpServletRequest request, HttpServletResponse response) {
    Authentication authenticationRequest = UsernamePasswordAuthenticationToken
            .unauthenticated(loginRequest.getLoginName(), loginRequest.getPassword());
    Authentication authenticationResponse = this.authenticationManager.authenticate(authenticationRequest);
    SecurityContext context = securityContextHolderStrategy.createEmptyContext();
    context.setAuthentication(authenticationResponse);
    securityContextHolderStrategy.setContext(context);
    securityContextRepository.saveContext(context, request, response);
    concurrentSessionControlAuthenticationStrategy.onAuthentication(authenticationResponse, request, response);
}

}


**equals() of My UserDetails(GJSJUser is the class username is distinct String)**
```    @Override
    public boolean equals(Object obj) {
        return obj instanceof GJSJUser ? this.getUsername().equals(((GJSJUser) obj).getUsername()) : false;
    }

It seems the loggin session is not added into concurrentmap in ServiceRegistry, so the sessionRegistry.getAllSessions is always empty. What's Wrong? Thanks a lot!

Comment From: kse-music

You should be registerNewSessionfirst, you can try to do like so, 1. Add RegisterSessionAuthenticationStrategy bean

   @Bean
    RegisterSessionAuthenticationStrategy registerSessionAuthenticationStrategy (SessionRegistry sessionRegistry) {
        return new RegisterSessionAuthenticationStrategy(sessionRegistry);
    }
  1. Use in LoginController
    @Autowired
    private RegisterSessionAuthenticationStrategy registerSessionAuthenticationStrategy ;

Invoke registerSessionAuthenticationStrategy.onAuthentication(authenticationResponse, request, response) before invoke concurrentSessionControlAuthenticationStrategy.onAuthentication(authenticationResponse, request, response)

Comment From: NieNoRc

Thank you. It's helpful. It can be achieved that preventing second login by set setExceptionIfMaximumExceeded(true). But If I want achieve: disable older session, I set setExceptionIfMaximumExceeded(false). I knew there is an expireNow() in onAuthentication(), and the old session is removed from SessionRegistry (the sessionRegistry.getAllSessions() returns no more than 1 element). But the old session is still valid. I implemente a SessionInformationExpiredStrategy, and inject it by .sessionManagement(x->x.sessionConcurrency(c->c.expiredSessionStrategy(new GJSJExpiredSessionStrategy()))), but when I debug the code, it not enter my own Strategy. So what should I do? Thanks!

Comment From: sjohnr

Thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. We prefer to use GitHub issues only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add a minimal sample that reproduces this issue if you feel this is a genuine bug.