@ -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