Skip to content

SessionRegistryImpl is now aware of SessionIdChangedEvent #5439

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.security.core.session;

import org.springframework.context.ApplicationEvent;

public abstract class SessionIdChangedEvent extends ApplicationEvent {

public SessionIdChangedEvent(Object source) {
super(source);
}

public abstract String getOldSessionId();

public abstract String getNewSessionId();
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.util.Assert;

Expand All @@ -40,7 +41,7 @@
* @author Luke Taylor
*/
public class SessionRegistryImpl implements SessionRegistry,
ApplicationListener<SessionDestroyedEvent> {
ApplicationListener<ApplicationEvent> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ApplicationEvent may be too generic to be used in this class. Perhaps we can create a new interface (e.g SessionEvent) that both SessionDestroyedEvent and SessionIdChangedEvent can implement.


// ~ Instance fields
// ================================================================================================
Expand Down Expand Up @@ -101,9 +102,18 @@ public SessionInformation getSessionInformation(String sessionId) {
return sessionIds.get(sessionId);
}

public void onApplicationEvent(SessionDestroyedEvent event) {
String sessionId = event.getId();
removeSessionInformation(sessionId);
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof SessionDestroyedEvent) {
SessionDestroyedEvent sessionDestroyedEvent = (SessionDestroyedEvent) event;
String sessionId = sessionDestroyedEvent.getId();
removeSessionInformation(sessionId);
} else if (event instanceof SessionIdChangedEvent) {
SessionIdChangedEvent sessionIdChangedEvent = (SessionIdChangedEvent) event;
String oldSessionId = sessionIdChangedEvent.getOldSessionId();
Object principal = sessionIds.get(oldSessionId).getPrincipal();
removeSessionInformation(oldSessionId);
registerNewSession(sessionIdChangedEvent.getNewSessionId(), principal);
}
}

public void refreshLastRequest(String sessionId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,33 @@ public List<SecurityContext> getSecurityContexts() {
assertThat(sessionRegistry.getSessionInformation(sessionId)).isNull();
}

@Test
public void sessionIdChangedEventRemovesOldSessionAndAddsANewSession() {
Object principal = "Some principal object";
final String sessionId = "zzzz";
final String newSessionId = "123";

// Register new Session
sessionRegistry.registerNewSession(sessionId, principal);

// De-register session via an ApplicationEvent
sessionRegistry.onApplicationEvent(new SessionIdChangedEvent("") {
@Override
public String getOldSessionId() {
return sessionId;
}

@Override
public String getNewSessionId() {
return newSessionId;
}
});

assertThat(sessionRegistry.getSessionInformation(sessionId)).isNull();
assertThat(sessionRegistry.getSessionInformation(newSessionId)).isNotNull();
assertThat(sessionRegistry.getSessionInformation(newSessionId).getPrincipal()).isEqualTo(principal);
}

@Test
public void testMultiplePrincipals() throws Exception {
Object principal1 = "principal_1";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionIdListener;
import javax.servlet.http.HttpSessionListener;

/**
Expand All @@ -44,7 +45,7 @@
*
* @author Ray Krueger
*/
public class HttpSessionEventPublisher implements HttpSessionListener {
public class HttpSessionEventPublisher implements HttpSessionListener, HttpSessionIdListener {
// ~ Static fields/initializers
// =====================================================================================

Expand Down Expand Up @@ -90,4 +91,16 @@ public void sessionDestroyed(HttpSessionEvent event) {

getContext(event.getSession().getServletContext()).publishEvent(e);
}

@Override
public void sessionIdChanged(HttpSessionEvent event, String oldSessionId) {
HttpSessionIdChangedEvent e = new HttpSessionIdChangedEvent(event.getSession(), oldSessionId);
Log log = LogFactory.getLog(LOGGER_NAME);

if (log.isDebugEnabled()) {
log.debug("Publishing event: " + e);
}

getContext(event.getSession().getServletContext()).publishEvent(e);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the new license header for new classes.

*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.security.web.session;

import javax.servlet.http.HttpSession;

import org.springframework.security.core.session.SessionIdChangedEvent;

/**
* Published by the {@link HttpSessionEventPublisher} when an {@code HttpSession} id
* is changed
*
*/
public class HttpSessionIdChangedEvent extends SessionIdChangedEvent {
private final String oldSessionId;
private final String newSessionid;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a small typo here, newSessionid should be newSessionId.

// ~ Constructors
// ===================================================================================================

public HttpSessionIdChangedEvent(HttpSession session, String oldSessionId) {
super(session);
this.oldSessionId = oldSessionId;
this.newSessionid = session.getId();
}

public String getOldSessionId() {
return oldSessionId;
}

@Override
public String getNewSessionId() {
return newSessionid;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ public void publishedEventIsReceivedbyListener() {
assertThat(listener.getDestroyedEvent()).isNotNull();
assertThat(listener.getCreatedEvent()).isNull();
assertThat(listener.getDestroyedEvent().getSession()).isEqualTo(session);

publisher.sessionIdChanged(event, "oldSessionId");
assertThat(listener.getSessionIdChangedEvent()).isNotNull();
assertThat(listener.getSessionIdChangedEvent().getOldSessionId()).isEqualTo("oldSessionId");
listener.setSessionIdChangedEvent(null);
}

@Test
Expand Down Expand Up @@ -108,6 +113,11 @@ public void publishedEventIsReceivedbyListenerChildContext() {
assertThat(listener.getDestroyedEvent()).isNotNull();
assertThat(listener.getCreatedEvent()).isNull();
assertThat(listener.getDestroyedEvent().getSession()).isEqualTo(session);

publisher.sessionIdChanged(event, "oldSessionId");
assertThat(listener.getSessionIdChangedEvent()).isNotNull();
assertThat(listener.getSessionIdChangedEvent().getOldSessionId()).isEqualTo("oldSessionId");
listener.setSessionIdChangedEvent(null);
}

// SEC-2599
Expand All @@ -131,4 +141,14 @@ public void sessionDestroyedNullApplicationContext() {

publisher.sessionDestroyed(event);
}

@Test(expected = IllegalStateException.class)
public void sessionIdChangeNullApplicationContext() {
HttpSessionEventPublisher publisher = new HttpSessionEventPublisher();
MockServletContext servletContext = new MockServletContext();
MockHttpSession session = new MockHttpSession(servletContext);
HttpSessionEvent event = new HttpSessionEvent(session);

publisher.sessionIdChanged(event, "oldSessionId");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class MockApplicationListener implements ApplicationListener<ApplicationE

private HttpSessionCreatedEvent createdEvent;
private HttpSessionDestroyedEvent destroyedEvent;
private HttpSessionIdChangedEvent sessionIdChangedEvent;

// ~ Methods
// ========================================================================================================
Expand All @@ -51,6 +52,9 @@ public void onApplicationEvent(ApplicationEvent event) {
else if (event instanceof HttpSessionDestroyedEvent) {
destroyedEvent = (HttpSessionDestroyedEvent) event;
}
else if (event instanceof HttpSessionIdChangedEvent) {
sessionIdChangedEvent = (HttpSessionIdChangedEvent) event;
}
}

public void setCreatedEvent(HttpSessionCreatedEvent createdEvent) {
Expand All @@ -60,4 +64,12 @@ public void setCreatedEvent(HttpSessionCreatedEvent createdEvent) {
public void setDestroyedEvent(HttpSessionDestroyedEvent destroyedEvent) {
this.destroyedEvent = destroyedEvent;
}

public void setSessionIdChangedEvent(HttpSessionIdChangedEvent sessionIdChangedEvent) {
this.sessionIdChangedEvent = sessionIdChangedEvent;
}

public HttpSessionIdChangedEvent getSessionIdChangedEvent() {
return sessionIdChangedEvent;
}
}