2323
2424import org .springframework .context .ApplicationEvent ;
2525import org .springframework .context .ApplicationEventPublisher ;
26+ import org .springframework .context .event .SimpleApplicationEventMulticaster ;
2627import org .springframework .mock .web .MockHttpServletRequest ;
2728import org .springframework .mock .web .MockHttpServletResponse ;
2829import org .springframework .security .core .Authentication ;
2930import org .springframework .security .core .session .SessionIdChangedEvent ;
31+ import org .springframework .security .core .session .SessionRegistryImpl ;
3032
3133import static org .assertj .core .api .Assertions .assertThat ;
3234import static org .mockito .Mockito .mock ;
@@ -47,6 +49,29 @@ public void applySessionFixation() {
4749 assertThat (request .getSession ().getId ()).isNotEqualTo (id );
4850 }
4951
52+ @ Test
53+ public void onAuthenticationWhenRegistryHasOldSessionThenMigratesWithoutHttpSessionEventPublisher () {
54+ // Reproduces gh-19007: without HttpSessionEventPublisher the old session ID used
55+ // to remain as a ghost entry in the registry after session fixation rotation,
56+ // causing ConcurrentSessionControlAuthenticationStrategy to count an extra session.
57+ SessionRegistryImpl registry = new SessionRegistryImpl ();
58+ SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster ();
59+ multicaster .addApplicationListener (registry );
60+ ChangeSessionIdAuthenticationStrategy strategy = new ChangeSessionIdAuthenticationStrategy ();
61+ strategy .setApplicationEventPublisher ((event ) -> {
62+ if (event instanceof ApplicationEvent applicationEvent ) {
63+ multicaster .multicastEvent (applicationEvent );
64+ }
65+ });
66+ MockHttpServletRequest request = new MockHttpServletRequest ();
67+ Object principal = "testPrincipal" ;
68+ registry .registerNewSession (request .getSession ().getId (), principal );
69+ strategy .onAuthentication (mock (Authentication .class ), request , new MockHttpServletResponse ());
70+ String newSessionId = request .getSession ().getId ();
71+ assertThat (registry .getSessionInformation (newSessionId )).isNotNull ();
72+ assertThat (registry .getAllSessions (principal , false )).hasSize (1 );
73+ }
74+
5075 @ Test
5176 public void onAuthenticationPublishesSessionIdChangedEventWithoutHttpSessionEventPublisher () {
5277 ChangeSessionIdAuthenticationStrategy strategy = new ChangeSessionIdAuthenticationStrategy ();
0 commit comments