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.UserDetails;
|
||||||
import net.sf.acegisecurity.ui.WebAuthenticationDetails;
|
import net.sf.acegisecurity.ui.WebAuthenticationDetails;
|
||||||
import net.sf.acegisecurity.ui.session.HttpSessionDestroyedEvent;
|
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.ApplicationEvent;
|
||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.context.ApplicationListener;
|
||||||
|
|
||||||
|
@ -46,17 +49,28 @@ import java.util.Set;
|
||||||
* @author Ben Alex
|
* @author Ben Alex
|
||||||
*/
|
*/
|
||||||
public class ConcurrentSessionControllerImpl
|
public class ConcurrentSessionControllerImpl
|
||||||
implements ConcurrentSessionController, ApplicationListener {
|
implements ConcurrentSessionController, ApplicationListener,
|
||||||
|
ApplicationContextAware {
|
||||||
//~ Instance fields ========================================================
|
//~ Instance fields ========================================================
|
||||||
|
|
||||||
protected Map principalsToSessions = new HashMap();
|
protected Map principalsToSessions = new HashMap();
|
||||||
protected Map sessionsToPrincipals = new HashMap();
|
protected Map sessionsToPrincipals = new HashMap();
|
||||||
protected Set sessionSet = new HashSet();
|
protected Set sessionSet = new HashSet();
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||||
private int maxSessions = 1;
|
private int maxSessions = 1;
|
||||||
|
|
||||||
//~ Methods ================================================================
|
//~ 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
|
* 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
|
* 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 request Used to retieve the {@link WebAuthenticationDetails}
|
||||||
* @param response Used to store the sessionId for the current Principal
|
* @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)
|
* @see #determineSessionPrincipal(net.sf.acegisecurity.Authentication)
|
||||||
*/
|
*/
|
||||||
public void afterAuthentication(Authentication request,
|
public void afterAuthentication(Authentication request,
|
||||||
Authentication response) {
|
Authentication response) throws ConcurrentLoginException {
|
||||||
enforceConcurrentLogins(response);
|
enforceConcurrentLogins(response);
|
||||||
|
|
||||||
if (request.getDetails() instanceof WebAuthenticationDetails) {
|
if (request.getDetails() instanceof WebAuthenticationDetails) {
|
||||||
|
@ -121,8 +137,8 @@ public class ConcurrentSessionControllerImpl
|
||||||
* {@link AuthenticationProvider}s
|
* {@link AuthenticationProvider}s
|
||||||
*
|
*
|
||||||
* @param request The Authentication in question
|
* @param request The Authentication in question
|
||||||
* @throws ConcurrentLoginException if the user has already met the {@link
|
* @throws ConcurrentLoginException If the user is already logged in the
|
||||||
* #setMaxSessions(int)}
|
* maximum number of times #setMaxSessions(int)}
|
||||||
*/
|
*/
|
||||||
public void beforeAuthentication(Authentication request)
|
public void beforeAuthentication(Authentication request)
|
||||||
throws ConcurrentLoginException {
|
throws ConcurrentLoginException {
|
||||||
|
@ -250,6 +266,9 @@ public class ConcurrentSessionControllerImpl
|
||||||
|
|
||||||
if (!isActiveSession(principal, sessionId)) {
|
if (!isActiveSession(principal, sessionId)) {
|
||||||
if (maxSessions == countSessions(principal)) {
|
if (maxSessions == countSessions(principal)) {
|
||||||
|
//Publish the event
|
||||||
|
publishViolationEvent(request);
|
||||||
|
|
||||||
//The user is AT their max, toss them out
|
//The user is AT their max, toss them out
|
||||||
throw new ConcurrentLoginException(principal
|
throw new ConcurrentLoginException(principal
|
||||||
+ " has reached the maximum concurrent logins");
|
+ " 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
|
* Remove the given sessionId from storage. Used by {@link
|
||||||
* #onApplicationEvent(org.springframework.context.ApplicationEvent)} for
|
* #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);
|
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 {
|
public void testImplementsApplicationListener() throws Exception {
|
||||||
assertTrue("This class must implement ApplicationListener, and at one point it didn't.",
|
assertTrue("This class must implement ApplicationListener, and at one point it didn't.",
|
||||||
target instanceof ApplicationListener);
|
target instanceof ApplicationListener);
|
||||||
|
|
Loading…
Reference in New Issue