SEC-1229: Removed legacy concurrency classes
This commit is contained in:
parent
7247902911
commit
2a1430f1ce
|
@ -1,14 +1,10 @@
|
|||
package org.springframework.security.config.authentication;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException;
|
||||
import org.springframework.context.support.AbstractXmlApplicationContext;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.concurrent.ConcurrentSessionControllerImpl;
|
||||
import org.springframework.security.authentication.concurrent.SessionRegistryImpl;
|
||||
import org.springframework.security.config.BeanIds;
|
||||
import org.springframework.security.config.util.InMemoryXmlApplicationContext;
|
||||
|
||||
/**
|
||||
|
@ -19,13 +15,6 @@ import org.springframework.security.config.util.InMemoryXmlApplicationContext;
|
|||
public class AuthenticationManagerBeanDefinitionParserTests {
|
||||
private AbstractXmlApplicationContext appContext;
|
||||
|
||||
private final String SESSION_CONTROLLER =
|
||||
"<b:bean id='sc' class='" + ConcurrentSessionControllerImpl.class.getName() + "'>" +
|
||||
" <b:property name='sessionRegistry'>" +
|
||||
" <b:bean class='" + SessionRegistryImpl.class.getName() + "'/>" +
|
||||
" </b:property>" +
|
||||
"</b:bean>";
|
||||
|
||||
@Test
|
||||
// SEC-1225
|
||||
public void providersAreRegisteredAsTopLevelBeans() throws Exception {
|
||||
|
@ -36,23 +25,10 @@ public class AuthenticationManagerBeanDefinitionParserTests {
|
|||
" <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +
|
||||
" </user-service>" +
|
||||
" </authentication-provider>" +
|
||||
"</authentication-manager>" + SESSION_CONTROLLER, "3.0");
|
||||
"</authentication-manager>", "3.0");
|
||||
assertEquals(1, appContext.getBeansOfType(AuthenticationProvider.class).size());
|
||||
}
|
||||
|
||||
@Test(expected=XmlBeanDefinitionStoreException.class)
|
||||
public void sessionControllerRefAttributeIsRejectedFor30Context() throws Exception {
|
||||
setContext(
|
||||
"<authentication-manager session-controller-ref='sc'>" +
|
||||
" <authentication-provider>" +
|
||||
" <user-service>" +
|
||||
" <user name='bob' password='bobspassword' authorities='ROLE_A,ROLE_B' />" +
|
||||
" </user-service>" +
|
||||
" </authentication-provider>" +
|
||||
"</authentication-manager>" + SESSION_CONTROLLER, "3.0");
|
||||
appContext.getBean(BeanIds.AUTHENTICATION_MANAGER);
|
||||
}
|
||||
|
||||
private void setContext(String context, String version) {
|
||||
appContext = new InMemoryXmlApplicationContext(context, version, null);
|
||||
}
|
||||
|
|
|
@ -8,10 +8,8 @@ import org.apache.commons.logging.Log;
|
|||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.security.authentication.concurrent.ConcurrentLoginException;
|
||||
import org.springframework.security.authentication.event.AbstractAuthenticationEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureConcurrentLoginEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureCredentialsExpiredEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureDisabledEvent;
|
||||
import org.springframework.security.authentication.event.AuthenticationFailureExpiredEvent;
|
||||
|
@ -70,8 +68,6 @@ public class DefaultAuthenticationEventPublisher implements AuthenticationEventP
|
|||
AuthenticationFailureBadCredentialsEvent.class.getName());
|
||||
exceptionMappings.put(UsernameNotFoundException.class.getName(),
|
||||
AuthenticationFailureBadCredentialsEvent.class.getName());
|
||||
exceptionMappings.put(ConcurrentLoginException.class.getName(),
|
||||
AuthenticationFailureConcurrentLoginEvent.class.getName());
|
||||
exceptionMappings.put(ProviderNotFoundException.class.getName(),
|
||||
AuthenticationFailureProviderNotFoundEvent.class.getName());
|
||||
exceptionMappings.put("org.springframework.security.authentication.cas.ProxyUntrustedException",
|
||||
|
|
|
@ -24,8 +24,6 @@ import org.springframework.beans.factory.InitializingBean;
|
|||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.MessageSourceAware;
|
||||
import org.springframework.context.support.MessageSourceAccessor;
|
||||
import org.springframework.security.authentication.concurrent.ConcurrentLoginException;
|
||||
import org.springframework.security.authentication.concurrent.ConcurrentSessionController;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||
|
@ -35,8 +33,6 @@ import org.springframework.util.Assert;
|
|||
/**
|
||||
* Iterates an {@link Authentication} request through a list of {@link AuthenticationProvider}s.
|
||||
*
|
||||
* Can optionally be configured with a {@link ConcurrentSessionController} to limit the number of sessions a user can
|
||||
* have.
|
||||
* <p>
|
||||
* <tt>AuthenticationProvider</tt>s are usually tried in order until one provides a non-null response.
|
||||
* A non-null response indicates the provider had authority to decide on the authentication request and no further
|
||||
|
@ -47,9 +43,8 @@ import org.springframework.util.Assert;
|
|||
* If no provider returns a non-null response, or indicates it can even process an <code>Authentication</code>,
|
||||
* the <code>ProviderManager</code> will throw a <code>ProviderNotFoundException</code>.
|
||||
* <p>
|
||||
* The exception to this process is when a provider throws an {@link AccountStatusException} or if the configured
|
||||
* concurrent session controller throws a {@link ConcurrentLoginException}. In both these cases, no further providers
|
||||
* in the list will be queried.
|
||||
* The exception to this process is when a provider throws an {@link AccountStatusException}, in which case no
|
||||
* further providers in the list will be queried.
|
||||
*
|
||||
* <h2>Event Publishing</h2>
|
||||
* <p>
|
||||
|
@ -68,7 +63,7 @@ import org.springframework.util.Assert;
|
|||
* @author Ben Alex
|
||||
* @author Luke Taylor
|
||||
* @version $Id$
|
||||
* @see ConcurrentSessionController
|
||||
*
|
||||
* @see DefaultAuthenticationEventPublisher
|
||||
*/
|
||||
public class ProviderManager extends AbstractAuthenticationManager implements MessageSourceAware, InitializingBean {
|
||||
|
@ -79,7 +74,6 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
|
|||
//~ Instance fields ================================================================================================
|
||||
|
||||
private AuthenticationEventPublisher eventPublisher = new NullEventPublisher();
|
||||
private ConcurrentSessionController sessionController = new NullConcurrentSessionController();
|
||||
private List<AuthenticationProvider> providers = Collections.emptyList();
|
||||
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
||||
private AuthenticationManager parent;
|
||||
|
@ -151,20 +145,12 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
|
|||
}
|
||||
}
|
||||
|
||||
// Finally check if the concurrent session controller will allow authentication
|
||||
try {
|
||||
if (result != null) {
|
||||
sessionController.checkAuthenticationAllowed(result);
|
||||
sessionController.registerSuccessfulAuthentication(result);
|
||||
eventPublisher.publishAuthenticationSuccess(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
} catch (AuthenticationException e) {
|
||||
lastException = e;
|
||||
if (result != null) {
|
||||
eventPublisher.publishAuthenticationSuccess(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Session control failed, parent was null, or didn't authenticate (or throw an exception).
|
||||
// Parent was null, or didn't authenticate (or throw an exception).
|
||||
|
||||
if (lastException == null) {
|
||||
lastException = new ProviderNotFoundException(messages.getMessage("ProviderManager.providerNotFound",
|
||||
|
@ -199,16 +185,6 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
|
|||
return providers;
|
||||
}
|
||||
|
||||
/**
|
||||
* The configured {@link ConcurrentSessionController} is returned or the {@link
|
||||
* NullConcurrentSessionController} if a specific one has not been set.
|
||||
*
|
||||
* @return {@link ConcurrentSessionController} instance
|
||||
*/
|
||||
ConcurrentSessionController getSessionController() {
|
||||
return sessionController;
|
||||
}
|
||||
|
||||
public void setMessageSource(MessageSource messageSource) {
|
||||
this.messages = new MessageSourceAccessor(messageSource);
|
||||
}
|
||||
|
@ -239,22 +215,8 @@ public class ProviderManager extends AbstractAuthenticationManager implements Me
|
|||
this.providers = providers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ConcurrentSessionController} to be used for limiting users' sessions.
|
||||
*
|
||||
* @param sessionController {@link ConcurrentSessionController}
|
||||
*/
|
||||
public void setSessionController(ConcurrentSessionController sessionController) {
|
||||
this.sessionController = sessionController;
|
||||
}
|
||||
|
||||
private static final class NullEventPublisher implements AuthenticationEventPublisher {
|
||||
public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) {}
|
||||
public void publishAuthenticationSuccess(Authentication authentication) {}
|
||||
}
|
||||
|
||||
private static final class NullConcurrentSessionController implements ConcurrentSessionController {
|
||||
public void checkAuthenticationAllowed(Authentication request) {}
|
||||
public void registerSuccessfulAuthentication(Authentication authentication) {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <code>ConcurrentSessionControllerImpl</code> if an attempt is made to login and the user has already
|
||||
* exceeded their maxmimum allowed sessions.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ConcurrentLoginException extends AuthenticationException {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public ConcurrentLoginException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
|
@ -1,174 +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 java.util.List;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.MessageSourceAware;
|
||||
import org.springframework.context.support.MessageSourceAccessor;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Base implementation of {@link ConcurrentSessionControllerImpl} which prohibits simultaneous logins.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ConcurrentSessionControllerImpl implements ConcurrentSessionController, InitializingBean,
|
||||
MessageSourceAware {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
|
||||
private SessionRegistry sessionRegistry;
|
||||
private boolean exceptionIfMaximumExceeded = false;
|
||||
private int maximumSessions = 1;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(sessionRegistry, "SessionRegistry required");
|
||||
Assert.isTrue(maximumSessions != 0,
|
||||
"MaximumLogins must be either -1 to allow unlimited logins, or a positive integer to specify a maximum");
|
||||
Assert.notNull(this.messages, "A message source must be set");
|
||||
}
|
||||
|
||||
public void checkAuthenticationAllowed(Authentication request) throws AuthenticationException {
|
||||
Assert.notNull(request, "Authentication request cannot be null (violation of interface contract)");
|
||||
|
||||
String sessionId = obtainSessionId(request);
|
||||
|
||||
final List<SessionInformation> sessions = sessionRegistry.getAllSessions(request.getPrincipal(), false);
|
||||
|
||||
int sessionCount = sessions == null ? 0 : sessions.size();
|
||||
|
||||
int allowableSessions = getMaximumSessionsForThisUser(request);
|
||||
Assert.isTrue(allowableSessions != 0, "getMaximumSessionsForThisUser() must return either -1 to allow "
|
||||
+ "unlimited logins, or a positive integer to specify a maximum");
|
||||
|
||||
if (sessionCount < allowableSessions) {
|
||||
// They haven't got too many login sessions running at present
|
||||
return;
|
||||
}
|
||||
|
||||
if (allowableSessions == -1) {
|
||||
// We permit unlimited logins
|
||||
return;
|
||||
}
|
||||
|
||||
if (sessionCount == allowableSessions) {
|
||||
// Only permit it though if this request is associated with one of the sessions
|
||||
for (SessionInformation si : sessions) {
|
||||
if (si.getSessionId().equals(sessionId)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allowableSessionsExceeded(sessionId, sessions, allowableSessions, sessionRegistry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows subclasses to customise behaviour when too many sessions are detected.
|
||||
*
|
||||
* @param sessionId the session ID of the present request
|
||||
* @param sessions either <code>null</code> or all unexpired sessions associated with the principal
|
||||
* @param allowableSessions the number of concurrent sessions the user is allowed to have
|
||||
* @param registry an instance of the <code>SessionRegistry</code> for subclass use
|
||||
*
|
||||
* @throws ConcurrentLoginException if the
|
||||
*/
|
||||
protected void allowableSessionsExceeded(String sessionId, List<SessionInformation> sessions, int allowableSessions,
|
||||
SessionRegistry registry) {
|
||||
if (exceptionIfMaximumExceeded || (sessions == null)) {
|
||||
throw new ConcurrentLoginException(messages.getMessage("ConcurrentSessionControllerImpl.exceededAllowed",
|
||||
new Object[] {new Integer(allowableSessions)},
|
||||
"Maximum sessions of {0} for this principal exceeded"));
|
||||
}
|
||||
|
||||
// Determine least recently used session, and mark it for invalidation
|
||||
SessionInformation leastRecentlyUsed = null;
|
||||
|
||||
for (int i = 0; i < sessions.size(); i++) {
|
||||
if ((leastRecentlyUsed == null)
|
||||
|| sessions.get(i).getLastRequest().before(leastRecentlyUsed.getLastRequest())) {
|
||||
leastRecentlyUsed = sessions.get(i);
|
||||
}
|
||||
}
|
||||
|
||||
leastRecentlyUsed.expireNow();
|
||||
}
|
||||
|
||||
public void registerSuccessfulAuthentication(Authentication authentication) {
|
||||
Assert.notNull(authentication, "Authentication cannot be null (violation of interface contract)");
|
||||
|
||||
sessionRegistry.registerNewSession(obtainSessionId(authentication), authentication.getPrincipal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method intended for use by subclasses to override the maximum number of sessions that are permitted for
|
||||
* a particular authentication. The default implementation simply returns the <code>maximumSessions</code> value
|
||||
* for the bean.
|
||||
*
|
||||
* @param authentication to determine the maximum sessions for
|
||||
*
|
||||
* @return either -1 meaning unlimited, or a positive integer to limit (never zero)
|
||||
*/
|
||||
protected int getMaximumSessionsForThisUser(Authentication authentication) {
|
||||
return maximumSessions;
|
||||
}
|
||||
|
||||
public void setExceptionIfMaximumExceeded(boolean exceptionIfMaximumExceeded) {
|
||||
this.exceptionIfMaximumExceeded = exceptionIfMaximumExceeded;
|
||||
}
|
||||
|
||||
public void setMaximumSessions(int maximumSessions) {
|
||||
this.maximumSessions = maximumSessions;
|
||||
}
|
||||
|
||||
public void setMessageSource(MessageSource messageSource) {
|
||||
this.messages = new MessageSourceAccessor(messageSource);
|
||||
}
|
||||
|
||||
public void setSessionRegistry(SessionRegistry sessionRegistry) {
|
||||
this.sessionRegistry = sessionRegistry;
|
||||
}
|
||||
|
||||
public SessionRegistry getSessionRegistry() {
|
||||
return sessionRegistry;
|
||||
}
|
||||
|
||||
private String obtainSessionId(Authentication auth) {
|
||||
if (auth.getDetails() == null || !(auth.getDetails() instanceof SessionIdentifierAware)) {
|
||||
throw new IllegalArgumentException("The 'details' property of the supplied Authentication " +
|
||||
"object must be set and must implement 'SessionIdentifierAware', but Authentication.getDetails() " +
|
||||
"returned " + auth.getDetails());
|
||||
}
|
||||
|
||||
String sessionId = ((SessionIdentifierAware) auth.getDetails()).getSessionId();
|
||||
Assert.hasText(sessionId, "SessionIdentifierAware did not return a Session ID (" + auth.getDetails() + ")");
|
||||
|
||||
return sessionId;
|
||||
}
|
||||
}
|
|
@ -1,35 +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.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
|
||||
/**
|
||||
* No-op implementation of {@link org.springframework.security.authentication.concurrent.ConcurrentSessionController}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
class NullConcurrentSessionController implements ConcurrentSessionController {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void checkAuthenticationAllowed(Authentication request)
|
||||
throws AuthenticationException {}
|
||||
|
||||
public void registerSuccessfulAuthentication(Authentication authentication) {}
|
||||
}
|
|
@ -1,35 +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.event;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
|
||||
/**
|
||||
* Application event which indicates authentication failure due to the user attempting to login to too many
|
||||
* concurrent sessions.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AuthenticationFailureConcurrentLoginEvent extends AbstractAuthenticationFailureEvent {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public AuthenticationFailureConcurrentLoginEvent(Authentication authentication, AuthenticationException exception) {
|
||||
super(authentication, exception);
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
package org.springframework.security.authentication;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -24,13 +25,6 @@ import java.util.List;
|
|||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.ProviderManager;
|
||||
import org.springframework.security.authentication.ProviderNotFoundException;
|
||||
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.ConcurrentSessionController;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
@ -81,18 +75,6 @@ public class ProviderManagerTests {
|
|||
verify(publisher).publishAuthenticationSuccess(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void concurrentSessionControllerConfiguration() throws Exception {
|
||||
ProviderManager target = new ProviderManager();
|
||||
|
||||
//The NullConcurrentSessionController should be the default
|
||||
assertNotNull(target.getSessionController());
|
||||
|
||||
ConcurrentSessionController csc = mock(ConcurrentSessionController.class);
|
||||
target.setSessionController(csc);
|
||||
assertSame(csc, target.getSessionController());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void startupFailsIfProviderListDoesNotContainProviders() throws Exception {
|
||||
List<Object> providers = new ArrayList<Object>();
|
||||
|
@ -193,18 +175,6 @@ public class ProviderManagerTests {
|
|||
verifyZeroInteractions(otherProvider);
|
||||
}
|
||||
|
||||
@Test(expected=ConcurrentLoginException.class)
|
||||
public void concurrentLoginExceptionPreventsCallsToSubsequentProviders() throws Exception {
|
||||
ProviderManager authMgr = makeProviderManager();
|
||||
// Two providers so if the second is polled it will throw an BadCredentialsException
|
||||
authMgr.setProviders(Arrays.asList(new MockProvider(), createProviderWhichThrows(new BadCredentialsException(""))) );
|
||||
TestingAuthenticationToken request = createAuthenticationToken();
|
||||
ConcurrentSessionController ctrlr = mock(ConcurrentSessionController.class);
|
||||
doThrow(new ConcurrentLoginException("mocked")).when(ctrlr).checkAuthenticationAllowed(request);
|
||||
authMgr.setSessionController(ctrlr);
|
||||
|
||||
authMgr.authenticate(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parentAuthenticationIsUsedIfProvidersDontAuthenticate() throws Exception {
|
||||
|
|
|
@ -1,112 +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 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;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link ConcurrentSessionControllerImpl}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ConcurrentSessionControllerImplTests {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
private static int nextSessionId = 1000;
|
||||
|
||||
private Authentication createAuthentication(String user, String password) {
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, password);
|
||||
auth.setDetails(new SessionIdentifierAware() {
|
||||
private final String id = Integer.toString(nextSessionId++);
|
||||
public String getSessionId() {
|
||||
return id;
|
||||
}
|
||||
});
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
@Test
|
||||
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 = ((SessionIdentifierAware) 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 = ((SessionIdentifierAware) auth3.getDetails()).getSessionId();
|
||||
assertTrue(registry.getSessionInformation(sessionId1).isExpired());
|
||||
assertFalse(registry.getSessionInformation(sessionId3).isExpired());
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void startupDetectsInvalidMaximumSessions() throws Exception {
|
||||
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
|
||||
sc.setMaximumSessions(0);
|
||||
|
||||
sc.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void startupDetectsInvalidSessionRegistry() throws Exception {
|
||||
ConcurrentSessionControllerImpl sc = new ConcurrentSessionControllerImpl();
|
||||
sc.setSessionRegistry(null);
|
||||
|
||||
sc.afterPropertiesSet();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue