Added the ConcurrentSessionViolationEvent that will be published by the ConcurrentSessionControllerImpl before throwing the ConcurrentSessionViolationException

This commit is contained in:
Ray Krueger 2005-03-25 00:53:46 +00:00
parent be20350737
commit 10c1926385
3 changed files with 83 additions and 4 deletions

View File

@ -21,6 +21,9 @@ import net.sf.acegisecurity.AuthenticationTrustResolverImpl;
import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.ui.WebAuthenticationDetails;
import net.sf.acegisecurity.ui.session.HttpSessionDestroyedEvent;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
@ -46,17 +49,28 @@ import java.util.Set;
* @author Ben Alex
*/
public class ConcurrentSessionControllerImpl
implements ConcurrentSessionController, ApplicationListener {
implements ConcurrentSessionController, ApplicationListener,
ApplicationContextAware {
//~ Instance fields ========================================================
protected Map principalsToSessions = new HashMap();
protected Map sessionsToPrincipals = new HashMap();
protected Set sessionSet = new HashSet();
private ApplicationContext applicationContext;
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
private int maxSessions = 1;
//~ Methods ================================================================
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* Set the maximum number of sessions a user is allowed to have, defaults
* to 1. Setting this to anything less than 1 will allow unlimited
@ -103,10 +117,12 @@ public class ConcurrentSessionControllerImpl
*
* @param request Used to retieve the {@link WebAuthenticationDetails}
* @param response Used to store the sessionId for the current Principal
* @throws ConcurrentLoginException If the user is already logged in the
* maximum number of times
* @see #determineSessionPrincipal(net.sf.acegisecurity.Authentication)
*/
public void afterAuthentication(Authentication request,
Authentication response) {
Authentication response) throws ConcurrentLoginException {
enforceConcurrentLogins(response);
if (request.getDetails() instanceof WebAuthenticationDetails) {
@ -121,8 +137,8 @@ public class ConcurrentSessionControllerImpl
* {@link AuthenticationProvider}s
*
* @param request The Authentication in question
* @throws ConcurrentLoginException if the user has already met the {@link
* #setMaxSessions(int)}
* @throws ConcurrentLoginException If the user is already logged in the
* maximum number of times #setMaxSessions(int)}
*/
public void beforeAuthentication(Authentication request)
throws ConcurrentLoginException {
@ -250,6 +266,9 @@ public class ConcurrentSessionControllerImpl
if (!isActiveSession(principal, sessionId)) {
if (maxSessions == countSessions(principal)) {
//Publish the event
publishViolationEvent(request);
//The user is AT their max, toss them out
throw new ConcurrentLoginException(principal
+ " has reached the maximum concurrent logins");
@ -258,6 +277,16 @@ public class ConcurrentSessionControllerImpl
}
}
/**
* Publish the even to the application context.
* The default action is to publish a new {@link ConcurrentSessionViolationEvent}
*
* @param auth The authentication object that caused the violation
*/
protected void publishViolationEvent(Authentication auth) {
getApplicationContext().publishEvent(new ConcurrentSessionViolationEvent(auth));
}
/**
* Remove the given sessionId from storage. Used by {@link
* #onApplicationEvent(org.springframework.context.ApplicationEvent)} for

View File

@ -0,0 +1,42 @@
/* 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 net.sf.acegisecurity.Authentication;
import org.springframework.context.ApplicationEvent;
/**
* Published by the ConcurrentSessionControllerImpl to notify the application
* context that a user has attempted to login more than the maximum times
* allowed by the {@link ConcurrentSessionControllerImpl#setMaxSessions(int)}
*
* @author Ray Krueger
*/
public class ConcurrentSessionViolationEvent extends ApplicationEvent {
//~ Constructors ===========================================================
public ConcurrentSessionViolationEvent(Authentication auth) {
super(auth);
}
//~ Methods ================================================================
public Authentication getAuthentication() {
return (Authentication) getSource();
}
}

View File

@ -141,6 +141,14 @@ public class ConcurrentSessionControllerImplTests extends TestCase {
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);