SEC-710: Refactor concurrent session handling support.

This commit is contained in:
Ben Alex
2005-10-22 01:53:03 +00:00
parent bad67782a8
commit 1ae07779a2
20 changed files with 1284 additions and 693 deletions

View File

@@ -0,0 +1,124 @@
/* Copyright 2004, 2005 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 net.sf.acegisecurity.concurrent;
import junit.framework.TestCase;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import net.sf.acegisecurity.ui.WebAuthenticationDetails;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpSession;
/**
* Tests {@link ConcurrentSessionControllerImpl}.
*
* @author Ben Alex
* @version $Id$
*/
public class ConcurrentSessionControllerImplTests extends TestCase {
//~ Methods ================================================================
public void testLifecycle() throws Exception {
// Build a test fixture
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
SessionRegistry registry = new SessionRegistryImpl();
sc.setSessionRegistry(registry);
// Attempt to authenticate - it should be successful
Authentication auth = createAuthentication("bob", "1212");
sc.checkAuthenticationAllowed(auth);
sc.registerSuccessfulAuthentication(auth);
String sessionId1 = ((WebAuthenticationDetails) auth.getDetails())
.getSessionId();
assertFalse(registry.getSessionInformation(sessionId1).isExpired());
// Attempt to authenticate again - it should still be successful
sc.checkAuthenticationAllowed(auth);
sc.registerSuccessfulAuthentication(auth);
// Attempt to authenticate with a different session for same principal - should fail
sc.setExceptionIfMaximumExceeded(true);
Authentication auth2 = createAuthentication("bob", "1212");
assertFalse(registry.getSessionInformation(sessionId1).isExpired());
try {
sc.checkAuthenticationAllowed(auth2);
fail("Should have thrown ConcurrentLoginException");
} catch (ConcurrentLoginException expected) {
assertTrue(true);
}
// Attempt to authenticate with a different session for same principal - should expire first session
sc.setExceptionIfMaximumExceeded(false);
Authentication auth3 = createAuthentication("bob", "1212");
sc.checkAuthenticationAllowed(auth3);
sc.registerSuccessfulAuthentication(auth3);
String sessionId3 = ((WebAuthenticationDetails) auth3.getDetails())
.getSessionId();
assertTrue(registry.getSessionInformation(sessionId1).isExpired());
assertFalse(registry.getSessionInformation(sessionId3).isExpired());
}
public void testStartupDetectsInvalidMaximumSessions()
throws Exception {
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
sc.setMaximumSessions(0);
try {
sc.afterPropertiesSet();
fail("Should have thrown IAE");
} catch (IllegalArgumentException expected) {
assertTrue(true);
}
}
public void testStartupDetectsInvalidSessionRegistry()
throws Exception {
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
sc.setSessionRegistry(null);
try {
sc.afterPropertiesSet();
fail("Should have thrown IAE");
} catch (IllegalArgumentException expected) {
assertTrue(true);
}
}
private Authentication createAuthentication(String user, String password) {
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user,
password);
auth.setDetails(createWebDetails(auth));
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);
}
}

View File

@@ -0,0 +1,173 @@
/* Copyright 2004, 2005 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 net.sf.acegisecurity.concurrent;
import junit.framework.TestCase;
import org.springframework.mock.web.MockFilterConfig;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockHttpSession;
import java.io.IOException;
import java.util.Date;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* Tests {@link ConcurrentSessionFilter}.
*
* @author Ben Alex
* @version $Id$
*/
public class ConcurrentSessionFilterTests extends TestCase {
//~ Constructors ===========================================================
public ConcurrentSessionFilterTests() {
super();
}
public ConcurrentSessionFilterTests(String arg0) {
super(arg0);
}
//~ Methods ================================================================
public static void main(String[] args) {
junit.textui.TestRunner.run(ConcurrentSessionFilterTests.class);
}
public void testDetectsExpiredSessions() throws Exception {
// Setup our HTTP request
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpSession session = new MockHttpSession();
request.setSession(session);
MockHttpServletResponse response = new MockHttpServletResponse();
MockFilterConfig config = new MockFilterConfig(null);
// Setup our expectation that the filter chain will not be invoked, as we redirect to expiredUrl
MockFilterChain chain = new MockFilterChain(false);
// Setup our test fixture and registry to want this session to be expired
ConcurrentSessionFilter filter = new ConcurrentSessionFilter();
SessionRegistry registry = new SessionRegistryImpl();
registry.registerNewSession(session.getId(), "principal");
registry.getSessionInformation(session.getId()).expireNow();
filter.setSessionRegistry(registry);
filter.setExpiredUrl("/expired.jsp");
// Test
executeFilterInContainerSimulator(config, filter, request, response,
chain);
assertEquals("/expired.jsp", response.getRedirectedUrl());
}
public void testDetectsMissingExpiredUrl() throws Exception {
ConcurrentSessionFilter filter = new ConcurrentSessionFilter();
filter.setSessionRegistry(new SessionRegistryImpl());
try {
filter.afterPropertiesSet();
fail("Should have thrown IAE");
} catch (IllegalArgumentException expected) {
assertTrue(true);
}
}
public void testDetectsMissingSessionRegistry() throws Exception {
ConcurrentSessionFilter filter = new ConcurrentSessionFilter();
filter.setExpiredUrl("xcx");
try {
filter.afterPropertiesSet();
fail("Should have thrown IAE");
} catch (IllegalArgumentException expected) {
assertTrue(true);
}
}
public void testUpdatesLastRequestTime() throws Exception {
// Setup our HTTP request
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpSession session = new MockHttpSession();
request.setSession(session);
MockHttpServletResponse response = new MockHttpServletResponse();
MockFilterConfig config = new MockFilterConfig(null);
// Setup our expectation that the filter chain will be invoked, as our session hasn't expired
MockFilterChain chain = new MockFilterChain(true);
// Setup our test fixture
ConcurrentSessionFilter filter = new ConcurrentSessionFilter();
SessionRegistry registry = new SessionRegistryImpl();
registry.registerNewSession(session.getId(), "principal");
Date lastRequest = registry.getSessionInformation(session.getId())
.getLastRequest();
filter.setSessionRegistry(registry);
filter.setExpiredUrl("/expired.jsp");
Thread.sleep(1000);
// Test
executeFilterInContainerSimulator(config, filter, request, response,
chain);
assertTrue(registry.getSessionInformation(session.getId())
.getLastRequest().after(lastRequest));
}
private void executeFilterInContainerSimulator(FilterConfig filterConfig,
Filter filter, ServletRequest request, ServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
filter.init(filterConfig);
filter.doFilter(request, response, filterChain);
filter.destroy();
}
//~ Inner Classes ==========================================================
private class MockFilterChain implements FilterChain {
private boolean expectToProceed;
public MockFilterChain(boolean expectToProceed) {
this.expectToProceed = expectToProceed;
}
private MockFilterChain() {
super();
}
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if (expectToProceed) {
assertTrue(true);
} else {
fail("Did not expect filter chain to proceed");
}
}
}
}

View File

@@ -0,0 +1,49 @@
/* Copyright 2004, 2005 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 net.sf.acegisecurity.concurrent;
import junit.framework.TestCase;
import java.util.Date;
/**
* Tests {@link SessionInformation}.
*
* @author Ben Alex
* @version $Id$
*/
public class SessionInformationTests extends TestCase {
//~ Methods ================================================================
public void testObject() throws Exception {
Object principal = "Some principal object";
String sessionId = "1234567890";
Date currentDate = new Date();
SessionInformation info = new SessionInformation(principal, sessionId,
currentDate);
assertEquals(principal, info.getPrincipal());
assertEquals(sessionId, info.getSessionId());
assertEquals(currentDate, info.getLastRequest());
Thread.sleep(1000);
info.refreshLastRequest();
assertTrue(info.getLastRequest().after(currentDate));
}
}

View File

@@ -0,0 +1,155 @@
/* Copyright 2004, 2005 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 net.sf.acegisecurity.concurrent;
import junit.framework.TestCase;
import net.sf.acegisecurity.ui.session.HttpSessionDestroyedEvent;
import org.springframework.mock.web.MockHttpSession;
import java.util.Date;
/**
* Tests {@link SessionRegistryImpl}.
*
* @author Ben Alex
* @version $Id$
*/
public class SessionRegistryImplTests extends TestCase {
//~ Methods ================================================================
public void testEventPublishing() {
MockHttpSession httpSession = new MockHttpSession();
Object principal = "Some principal object";
String sessionId = httpSession.getId();
assertNotNull(sessionId);
SessionRegistryImpl sessionRegistry = new SessionRegistryImpl();
// Register new Session
sessionRegistry.registerNewSession(sessionId, principal);
// Deregister session via an ApplicationEvent
sessionRegistry.onApplicationEvent(new HttpSessionDestroyedEvent(
httpSession));
// Check attempts to retrieve cleared session return null
assertNull(sessionRegistry.getSessionInformation(sessionId));
}
public void testSessionInformationLifecycle() throws Exception {
Object principal = "Some principal object";
String sessionId = "1234567890";
SessionRegistryImpl sessionRegistry = new SessionRegistryImpl();
// Register new Session
sessionRegistry.registerNewSession(sessionId, principal);
// Retrieve existing session by session ID
Date currentDateTime = sessionRegistry.getSessionInformation(sessionId)
.getLastRequest();
assertEquals(principal,
sessionRegistry.getSessionInformation(sessionId).getPrincipal());
assertEquals(sessionId,
sessionRegistry.getSessionInformation(sessionId).getSessionId());
assertNotNull(sessionRegistry.getSessionInformation(sessionId)
.getLastRequest());
// Retrieve existing session by principal
assertEquals(1, sessionRegistry.getAllSessions(principal).length);
// Sleep to ensure SessionRegistryImpl will update time
Thread.sleep(1000);
// Update request date/time
sessionRegistry.refreshLastRequest(sessionId);
Date retrieved = sessionRegistry.getSessionInformation(sessionId)
.getLastRequest();
assertTrue(retrieved.after(currentDateTime));
// Check it retrieves correctly when looked up via principal
assertEquals(retrieved,
sessionRegistry.getAllSessions(principal)[0].getLastRequest());
// Clear session information
sessionRegistry.removeSessionInformation(sessionId);
// Check attempts to retrieve cleared session return null
assertNull(sessionRegistry.getSessionInformation(sessionId));
assertNull(sessionRegistry.getAllSessions(principal));
}
public void testTwoSessionsOnePrincipalHandling() throws Exception {
Object principal = "Some principal object";
String sessionId1 = "1234567890";
String sessionId2 = "9876543210";
SessionRegistryImpl sessionRegistry = new SessionRegistryImpl();
// Register new Session
sessionRegistry.registerNewSession(sessionId1, principal);
assertEquals(1, sessionRegistry.getAllSessions(principal).length);
assertEquals(sessionId1,
sessionRegistry.getAllSessions(principal)[0].getSessionId());
// Register new Session
sessionRegistry.registerNewSession(sessionId2, principal);
assertEquals(2, sessionRegistry.getAllSessions(principal).length);
assertEquals(sessionId2,
sessionRegistry.getAllSessions(principal)[1].getSessionId());
// Clear session information
sessionRegistry.removeSessionInformation(sessionId1);
assertEquals(1, sessionRegistry.getAllSessions(principal).length);
assertEquals(sessionId2,
sessionRegistry.getAllSessions(principal)[0].getSessionId());
// Clear final session
sessionRegistry.removeSessionInformation(sessionId2);
assertNull(sessionRegistry.getSessionInformation(sessionId2));
assertNull(sessionRegistry.getAllSessions(principal));
}
public void testTwoSessionsOnePrincipalExpiring() throws Exception {
Object principal = "Some principal object";
String sessionId1 = "1234567890";
String sessionId2 = "9876543210";
SessionRegistryImpl sessionRegistry = new SessionRegistryImpl();
// Register new Session
sessionRegistry.registerNewSession(sessionId1, principal);
assertEquals(1, sessionRegistry.getAllSessions(principal).length);
assertEquals(sessionId1,
sessionRegistry.getAllSessions(principal)[0].getSessionId());
// Register new Session
sessionRegistry.registerNewSession(sessionId2, principal);
assertEquals(2, sessionRegistry.getAllSessions(principal).length);
assertEquals(sessionId2,
sessionRegistry.getAllSessions(principal)[1].getSessionId());
// Expire one session
SessionInformation session = sessionRegistry.getSessionInformation(sessionId2);
session.expireNow();
// Check retrieval still correct
assertTrue(sessionRegistry.getSessionInformation(sessionId2).isExpired());
assertFalse(sessionRegistry.getSessionInformation(sessionId1).isExpired());
}
}

View File

@@ -1,280 +0,0 @@
/* Copyright 2004, 2005 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 net.sf.acegisecurity.providers;
import junit.framework.TestCase;
import net.sf.acegisecurity.providers.anonymous.AnonymousAuthenticationToken;
import net.sf.acegisecurity.providers.dao.User;
import net.sf.acegisecurity.ui.WebAuthenticationDetails;
import net.sf.acegisecurity.ui.session.HttpSessionCreatedEvent;
import net.sf.acegisecurity.ui.session.HttpSessionDestroyedEvent;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.AuthenticationTrustResolverImpl;
import net.sf.acegisecurity.MockApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.mock.web.MockHttpServletRequest;
import java.security.Principal;
/**
* Tests for {@link ConcurrentSessionControllerImpl}
*
* @author Ray Krueger
* @author Luke Taylor
* @version $Id$
*/
public class ConcurrentSessionControllerImplTests extends TestCase {
//~ Instance fields ========================================================
ConcurrentSessionControllerImpl target;
//~ Methods ================================================================
public void testAnonymous() throws Exception {
AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken("blah",
"anon",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ANON")});
target.beforeAuthentication(auth);
target.afterAuthentication(auth, auth);
}
public void testBumpCoverage() throws Exception {
target.onApplicationEvent(new HttpSessionCreatedEvent(
new MockHttpSession()));
}
public void testEnforcementKnownGood() throws Exception {
Authentication auth = createAuthentication("user", "password");
target.beforeAuthentication(auth);
target.afterAuthentication(auth, auth);
}
public void testEnforcementMultipleSessions() throws Exception {
target.setMaxSessions(5);
Authentication auth = null;
for (int i = 0; i < 5; i++) { // creates 5 sessions
auth = createAuthentication("user", "password");
target.beforeAuthentication(auth);
target.afterAuthentication(auth, auth);
}
try {
auth = createAuthentication("user", "password");
target.beforeAuthentication(auth);
fail(
"Only allowed 5 sessions, this should have thrown a ConcurrentLoginException");
} catch (ConcurrentLoginException e) {
assertTrue(e.getMessage().startsWith(auth.getPrincipal().toString()));
}
}
public void testEnforcementSingleSession() throws Exception {
target.setMaxSessions(1);
Authentication auth = createAuthentication("user", "password");
target.beforeAuthentication(auth);
target.afterAuthentication(auth, auth);
try {
target.beforeAuthentication(createAuthentication("user", "password"));
fail(
"Only allowed 1 session, this should have thrown a ConcurrentLoginException");
} catch (ConcurrentLoginException e) {}
}
public void testEnforcementUnlimitedSameSession() throws Exception {
target.setMaxSessions(1);
MockHttpSession session = new MockHttpSession(); // all requests are within this session
for (int i = 0; i < 100; i++) {
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("user",
"password");
MockHttpServletRequest request = new MockHttpServletRequest();
request.setSession(session);
request.setUserPrincipal(auth);
auth.setDetails(new WebAuthenticationDetails(request));
target.beforeAuthentication(auth);
target.afterAuthentication(auth, auth);
}
}
public void testEnforcementUnlimitedSessions() throws Exception {
target.setMaxSessions(0);
for (int i = 0; i < 100; i++) {
Authentication auth = createAuthentication("user", "password");
target.beforeAuthentication(auth);
target.afterAuthentication(auth, auth);
}
}
public void testEventHandler() throws Exception {
target.setMaxSessions(1);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("user",
"password");
MockHttpSession session = new MockHttpSession();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setSession(session);
request.setUserPrincipal(auth);
auth.setDetails(new WebAuthenticationDetails(request));
target.beforeAuthentication(auth);
target.afterAuthentication(auth, auth);
target.onApplicationEvent(new HttpSessionDestroyedEvent(session));
Authentication different = createAuthentication("user", "password");
target.beforeAuthentication(different);
target.afterAuthentication(different, different);
}
public void testEventObject() {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user",
"password");
ConcurrentSessionViolationEvent ev = new ConcurrentSessionViolationEvent(token);
assertEquals("The token that went in should be the token that comes out",
token, ev.getAuthentication());
}
public void testImplementsApplicationListener() throws Exception {
assertTrue("This class must implement ApplicationListener, and at one point it didn't.",
target instanceof ApplicationListener);
}
public void testNonWebDetails() throws Exception {
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("asdf",
"asdf");
auth.setDetails("Hi there");
target.beforeAuthentication(auth);
target.afterAuthentication(auth, auth);
}
public void testPrincipals() throws Exception {
target.setMaxSessions(1);
final UserDetails user = new User("user", "password", true, true, true,
true, new GrantedAuthority[0]);
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user,
"password", user.getAuthorities());
auth.setDetails(createWebDetails(auth));
target.beforeAuthentication(auth);
target.afterAuthentication(auth, auth);
try {
UsernamePasswordAuthenticationToken otherAuth = new UsernamePasswordAuthenticationToken(new Principal() {
public String getName() {
return "user";
}
public String toString() {
return getName();
}
}, "password");
otherAuth.setDetails(createWebDetails(otherAuth));
target.beforeAuthentication(otherAuth);
fail(
"Same principal, different principal type, different session should have thrown ConcurrentLoginException");
} catch (ConcurrentLoginException e) {}
}
public void testSetMax() throws Exception {
target.setMaxSessions(1);
assertEquals(1, target.getMaxSessions());
target.setMaxSessions(2);
assertEquals(2, target.getMaxSessions());
}
public void testSetTrustManager() throws Exception {
assertNotNull("There is supposed to be a default AuthenticationTrustResolver",
target.getTrustResolver());
AuthenticationTrustResolverImpl impl = new AuthenticationTrustResolverImpl();
target.setTrustResolver(impl);
assertEquals(impl, target.getTrustResolver());
}
public void testUtilityMethods() throws Exception {
Object key = new Object();
target.addSession(key, "1");
target.addSession(key, "2");
target.addSession(key, "3");
target.removeSession("2");
assertFalse(target.isActiveSession(key, "2"));
assertTrue(target.isActiveSession(key, "1"));
assertTrue(target.isActiveSession(key, "3"));
assertNull(target.sessionsToPrincipals.get("2"));
assertEquals(2, target.countSessions(key));
target.addSession(key, "2");
assertEquals(3, target.countSessions(key));
target.addSession(key, "2");
target.addSession(key, "2");
assertEquals(3, target.countSessions(key));
assertTrue(target.isActiveSession(key, "1"));
assertTrue(target.isActiveSession(key, "2"));
assertTrue(target.isActiveSession(key, "3"));
assertFalse(target.isActiveSession(key, "nope"));
assertFalse(target.isActiveSession(new Object(), "1"));
assertFalse(target.isActiveSession(new Object(), "1"));
target.removeSession("nothing to see here");
}
protected void setUp() throws Exception {
target = new ConcurrentSessionControllerImpl();
target.setApplicationContext(MockApplicationContext.getContext());
}
private Authentication createAuthentication(String user, String password) {
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user,
password);
auth.setDetails(createWebDetails(auth));
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);
}
}

View File

@@ -18,6 +18,8 @@ package net.sf.acegisecurity.providers;
import junit.framework.TestCase;
import net.sf.acegisecurity.*;
import net.sf.acegisecurity.concurrent.ConcurrentSessionControllerImpl;
import net.sf.acegisecurity.concurrent.NullConcurrentSessionController;
import java.util.List;
import java.util.Vector;