Refactored SessionRegistryImpl to remove servlet API deps and moved back into core, along with other concurrent authentication package classes.
This commit is contained in:
parent
75d5e8f5f2
commit
cac2bce382
|
@ -11,8 +11,8 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
|||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl;
|
||||
import org.springframework.security.authentication.concurrent.SessionRegistryImpl;
|
||||
import org.springframework.security.web.concurrent.ConcurrentSessionFilter;
|
||||
import org.springframework.security.web.concurrent.SessionRegistryImpl;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.springframework.security.authentication.TestingAuthenticationToken;
|
|||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.authentication.concurrent.ConcurrentLoginException;
|
||||
import org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl;
|
||||
import org.springframework.security.authentication.concurrent.SessionRegistryImpl;
|
||||
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.openid.OpenIDAuthenticationProcessingFilter;
|
||||
|
@ -51,7 +52,6 @@ import org.springframework.security.web.authentication.rememberme.PersistentToke
|
|||
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
|
||||
import org.springframework.security.web.authentication.www.BasicProcessingFilter;
|
||||
import org.springframework.security.web.concurrent.ConcurrentSessionFilter;
|
||||
import org.springframework.security.web.concurrent.SessionRegistryImpl;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
|
||||
import org.springframework.security.web.expression.DefaultWebSecurityExpressionHandler;
|
||||
|
|
|
@ -7,11 +7,11 @@ import org.junit.Test;
|
|||
import org.springframework.context.support.AbstractXmlApplicationContext;
|
||||
import org.springframework.security.authentication.concurrent.ConcurrentSessionController;
|
||||
import org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl;
|
||||
import org.springframework.security.authentication.concurrent.SessionRegistryImpl;
|
||||
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
import org.springframework.security.web.concurrent.SessionRegistryImpl;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.authentication.concurrent;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
|
||||
/**
|
||||
* Thrown by a <code>SessionRegistry</code> implementation if an attempt is made to create new session information
|
||||
* for an existing sessionId. The user should firstly clear the existing session from the
|
||||
* <code>ConcurrentSessionRegistry</code>.
|
||||
*
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public class SessionAlreadyUsedException extends AuthenticationException {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public SessionAlreadyUsedException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
|
@ -67,11 +67,8 @@ public interface SessionRegistry {
|
|||
*
|
||||
* @param sessionId to associate with the principal (should never be <code>null</code>)
|
||||
* @param principal to associate with the session (should never be <code>null</code>)
|
||||
*
|
||||
* @throws SessionAlreadyUsedException DOCUMENT ME!
|
||||
*/
|
||||
void registerNewSession(String sessionId, Object principal)
|
||||
throws SessionAlreadyUsedException;
|
||||
void registerNewSession(String sessionId, Object principal);
|
||||
|
||||
/**
|
||||
* Deletes all the session information being maintained for the specified <code>sessionId</code>. If the
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.web.concurrent;
|
||||
package org.springframework.security.authentication.concurrent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -24,15 +24,10 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
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.security.authentication.concurrent.SessionInformation;
|
||||
import org.springframework.security.authentication.concurrent.SessionRegistry;
|
||||
import org.springframework.security.web.session.HttpSessionDestroyedEvent;
|
||||
import org.springframework.security.core.session.SessionDestroyedEvent;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
|
@ -48,7 +43,7 @@ import org.springframework.util.Assert;
|
|||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SessionRegistryImpl implements SessionRegistry, ApplicationListener {
|
||||
public class SessionRegistryImpl implements SessionRegistry, ApplicationListener<SessionDestroyedEvent> {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
protected static final Log logger = LogFactory.getLog(SessionRegistryImpl.class);
|
||||
|
@ -98,11 +93,9 @@ public class SessionRegistryImpl implements SessionRegistry, ApplicationListener
|
|||
return (SessionInformation) sessionIds.get(sessionId);
|
||||
}
|
||||
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (event instanceof HttpSessionDestroyedEvent) {
|
||||
String sessionId = ((HttpSession) event.getSource()).getId();
|
||||
removeSessionInformation(sessionId);
|
||||
}
|
||||
public void onApplicationEvent(SessionDestroyedEvent event) {
|
||||
String sessionId = event.getId();
|
||||
removeSessionInformation(sessionId);
|
||||
}
|
||||
|
||||
public void refreshLastRequest(String sessionId) {
|
|
@ -23,4 +23,10 @@ public abstract class SessionDestroyedEvent extends ApplicationEvent {
|
|||
* @return the <tt>SecurityContext</tt> associated with the session, or null if there is no context.
|
||||
*/
|
||||
public abstract SecurityContext getSecurityContext();
|
||||
|
||||
/**
|
||||
* The identifier associated with the destroyed session.
|
||||
* @return
|
||||
*/
|
||||
public abstract String getId();
|
||||
}
|
||||
|
|
|
@ -13,23 +13,19 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.web.concurrent;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
package org.springframework.security.authentication.concurrent;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.authentication.concurrent.ConcurrentLoginException;
|
||||
import org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl;
|
||||
import org.springframework.security.authentication.concurrent.SessionIdentifierAware;
|
||||
import org.springframework.security.authentication.concurrent.SessionRegistry;
|
||||
import org.springframework.security.authentication.concurrent.SessionRegistryImpl;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||
import org.springframework.security.web.concurrent.SessionRegistryImpl;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link ConcurrentSessionControllerImpl}.
|
||||
|
@ -37,25 +33,24 @@ import org.springframework.mock.web.MockHttpSession;
|
|||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ConcurrentSessionControllerImplTests extends TestCase {
|
||||
public class ConcurrentSessionControllerImplTests {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private static int nextSessionId = 1000;
|
||||
|
||||
private Authentication createAuthentication(String user, String password) {
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, password);
|
||||
auth.setDetails(createWebDetails(auth));
|
||||
auth.setDetails(new SessionIdentifierAware() {
|
||||
private final String id = Integer.toString(nextSessionId++);
|
||||
public String getSessionId() {
|
||||
return id;
|
||||
}
|
||||
});
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
private WebAuthenticationDetails createWebDetails(Authentication auth) {
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setSession(session);
|
||||
request.setUserPrincipal(auth);
|
||||
|
||||
return new WebAuthenticationDetails(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycle() throws Exception {
|
||||
// Build a test fixture
|
||||
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
|
||||
|
@ -67,7 +62,7 @@ public class ConcurrentSessionControllerImplTests extends TestCase {
|
|||
sc.checkAuthenticationAllowed(auth);
|
||||
sc.registerSuccessfulAuthentication(auth);
|
||||
|
||||
String sessionId1 = ((WebAuthenticationDetails) auth.getDetails()).getSessionId();
|
||||
String sessionId1 = ((SessionIdentifierAware) auth.getDetails()).getSessionId();
|
||||
assertFalse(registry.getSessionInformation(sessionId1).isExpired());
|
||||
|
||||
// Attempt to authenticate again - it should still be successful
|
||||
|
@ -94,34 +89,24 @@ public class ConcurrentSessionControllerImplTests extends TestCase {
|
|||
sc.checkAuthenticationAllowed(auth3);
|
||||
sc.registerSuccessfulAuthentication(auth3);
|
||||
|
||||
String sessionId3 = ((WebAuthenticationDetails) auth3.getDetails()).getSessionId();
|
||||
String sessionId3 = ((SessionIdentifierAware) auth3.getDetails()).getSessionId();
|
||||
assertTrue(registry.getSessionInformation(sessionId1).isExpired());
|
||||
assertFalse(registry.getSessionInformation(sessionId3).isExpired());
|
||||
}
|
||||
|
||||
public void testStartupDetectsInvalidMaximumSessions()
|
||||
throws Exception {
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void startupDetectsInvalidMaximumSessions() throws Exception {
|
||||
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
|
||||
sc.setMaximumSessions(0);
|
||||
|
||||
try {
|
||||
sc.afterPropertiesSet();
|
||||
fail("Should have thrown IAE");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
sc.afterPropertiesSet();
|
||||
}
|
||||
|
||||
public void testStartupDetectsInvalidSessionRegistry()
|
||||
throws Exception {
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void startupDetectsInvalidSessionRegistry() throws Exception {
|
||||
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
|
||||
sc.setSessionRegistry(null);
|
||||
|
||||
try {
|
||||
sc.afterPropertiesSet();
|
||||
fail("Should have thrown IAE");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
sc.afterPropertiesSet();
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.web.concurrent;
|
||||
package org.springframework.security.authentication.concurrent;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
|
@ -13,49 +13,59 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.security.web.concurrent;
|
||||
package org.springframework.security.authentication.concurrent;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.security.authentication.concurrent.SessionInformation;
|
||||
import org.springframework.security.web.concurrent.SessionRegistryImpl;
|
||||
import org.springframework.security.web.session.HttpSessionDestroyedEvent;
|
||||
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.session.SessionDestroyedEvent;
|
||||
|
||||
/**
|
||||
* Tests {@link SessionRegistryImpl}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SessionRegistryImplTests extends TestCase {
|
||||
public class SessionRegistryImplTests {
|
||||
private SessionRegistryImpl sessionRegistry;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
sessionRegistry = new SessionRegistryImpl();
|
||||
}
|
||||
|
||||
public void testEventPublishing() {
|
||||
MockHttpSession httpSession = new MockHttpSession();
|
||||
@Test
|
||||
public void sessionDestroyedEventRemovesSessionFromRegistry() {
|
||||
Object principal = "Some principal object";
|
||||
String sessionId = httpSession.getId();
|
||||
assertNotNull(sessionId);
|
||||
final String sessionId = "zzzz";
|
||||
|
||||
// Register new Session
|
||||
sessionRegistry.registerNewSession(sessionId, principal);
|
||||
|
||||
// Deregister session via an ApplicationEvent
|
||||
sessionRegistry.onApplicationEvent(new HttpSessionDestroyedEvent(httpSession));
|
||||
// De-register session via an ApplicationEvent
|
||||
sessionRegistry.onApplicationEvent(new SessionDestroyedEvent("") {
|
||||
@Override
|
||||
public String getId() {
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecurityContext getSecurityContext() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Check attempts to retrieve cleared session return null
|
||||
assertNull(sessionRegistry.getSessionInformation(sessionId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiplePrincipals() throws Exception {
|
||||
Object principal1 = "principal_1";
|
||||
Object principal2 = "principal_2";
|
||||
|
@ -71,6 +81,7 @@ public class SessionRegistryImplTests extends TestCase {
|
|||
assertEquals(principal2, sessionRegistry.getAllPrincipals()[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSessionInformationLifecycle() throws Exception {
|
||||
Object principal = "Some principal object";
|
||||
String sessionId = "1234567890";
|
||||
|
@ -106,6 +117,7 @@ public class SessionRegistryImplTests extends TestCase {
|
|||
assertNull(sessionRegistry.getAllSessions(principal, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoSessionsOnePrincipalExpiring() throws Exception {
|
||||
Object principal = "Some principal object";
|
||||
String sessionId1 = "1234567890";
|
||||
|
@ -130,6 +142,7 @@ public class SessionRegistryImplTests extends TestCase {
|
|||
assertFalse(sessionRegistry.getSessionInformation(sessionId1).isExpired());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoSessionsOnePrincipalHandling() throws Exception {
|
||||
Object principal = "Some principal object";
|
||||
String sessionId1 = "1234567890";
|
||||
|
@ -155,7 +168,7 @@ public class SessionRegistryImplTests extends TestCase {
|
|||
assertNull(sessionRegistry.getAllSessions(principal, false));
|
||||
}
|
||||
|
||||
boolean contains(String sessionId, Object principal) {
|
||||
private boolean contains(String sessionId, Object principal) {
|
||||
SessionInformation[] info = sessionRegistry.getAllSessions(principal, false);
|
||||
|
||||
for (int i = 0; i < info.length; i++) {
|
|
@ -35,11 +35,17 @@ public class HttpSessionDestroyedEvent extends SessionDestroyedEvent {
|
|||
super(session);
|
||||
}
|
||||
|
||||
public HttpSession getSession() {
|
||||
return (HttpSession) getSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecurityContext getSecurityContext() {
|
||||
return (SecurityContext) ((HttpSession)getSource()).getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
|
||||
}
|
||||
|
||||
public HttpSession getSession() {
|
||||
return (HttpSession) getSource();
|
||||
@Override
|
||||
public String getId() {
|
||||
return getSession().getId();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ import org.springframework.mock.web.MockHttpServletRequest;
|
|||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.security.authentication.concurrent.SessionRegistry;
|
||||
import org.springframework.security.authentication.concurrent.SessionRegistryImpl;
|
||||
import org.springframework.security.web.concurrent.ConcurrentSessionFilter;
|
||||
import org.springframework.security.web.concurrent.SessionRegistryImpl;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
|
|
Loading…
Reference in New Issue