Added the ConcurrentSessionViolationEvent that will be published by the ConcurrentSessionControllerImpl before throwing the ConcurrentSessionViolationException
This commit is contained in:
parent
be20350737
commit
10c1926385
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue