Ver Fonte

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

Ray Krueger há 20 anos atrás
pai
commit
10c1926385

+ 33 - 4
core/src/main/java/org/acegisecurity/providers/ConcurrentSessionControllerImpl.java

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

+ 42 - 0
core/src/main/java/org/acegisecurity/providers/ConcurrentSessionViolationEvent.java

@@ -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();
+    }
+}

+ 8 - 0
core/src/test/java/org/acegisecurity/providers/ConcurrentSessionControllerImplTests.java

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