瀏覽代碼

SEC-243: SessionRegistry.getAllSessions() now accepts an "includeExpiredSessions" argument.

Ben Alex 19 年之前
父節點
當前提交
0648c65b0b

+ 47 - 42
core/src/main/java/org/acegisecurity/concurrent/ConcurrentSessionControllerImpl.java

@@ -1,4 +1,4 @@
-/* Copyright 2004, 2005 Acegi Technology Pty Limited
+/* Copyright 2004, 2005, 2006 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.
@@ -18,30 +18,35 @@ package org.acegisecurity.concurrent;
 import org.acegisecurity.AcegiMessageSource;
 import org.acegisecurity.Authentication;
 import org.acegisecurity.AuthenticationException;
+
 import org.springframework.beans.factory.InitializingBean;
+
 import org.springframework.context.MessageSource;
 import org.springframework.context.MessageSourceAware;
 import org.springframework.context.support.MessageSourceAccessor;
+
 import org.springframework.util.Assert;
 
 
 /**
  * Base implementation of {@link ConcurrentSessionControllerImpl} which
  * prohibits simultaneous logins.
+ * 
  * <p>
- * By default uses {@link SessionRegistryImpl},
- * although any <code>SessionRegistry</code> may be used.
+ * By default uses {@link SessionRegistryImpl}, although any
+ * <code>SessionRegistry</code> may be used.
  * </p>
  *
  * @author Ben Alex
  * @version $Id$
  */
-public class ConcurrentSessionControllerImpl implements ConcurrentSessionController,
-        InitializingBean, MessageSourceAware {
-
+public class ConcurrentSessionControllerImpl
+    implements ConcurrentSessionController, InitializingBean,
+        MessageSourceAware {
     //~ Instance fields ========================================================
 
-    protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
+    protected MessageSourceAccessor messages = AcegiMessageSource
+        .getAccessor();
     private SessionRegistry sessionRegistry = new SessionRegistryImpl();
     private boolean exceptionIfMaximumExceeded = false;
     private int maximumSessions = 1;
@@ -51,7 +56,7 @@ public class ConcurrentSessionControllerImpl implements ConcurrentSessionControl
     public void afterPropertiesSet() throws Exception {
         Assert.notNull(sessionRegistry, "SessionRegistry required");
         Assert.isTrue(maximumSessions != 0,
-                "MaximumLogins must be either -1 to allow unlimited logins, or a positive integer to specify a maximum");
+            "MaximumLogins must be either -1 to allow unlimited logins, or a positive integer to specify a maximum");
         Assert.notNull(this.messages, "A message source must be set");
     }
 
@@ -59,21 +64,22 @@ public class ConcurrentSessionControllerImpl implements ConcurrentSessionControl
      * Allows subclasses to customise behaviour when too many sessions are
      * detected.
      *
-     * @param sessionId         the session ID of the present request
-     * @param sessions          either <code>null</code> or all unexpired sessions
-     *                          associated with the principal
+     * @param sessionId the session ID of the present request
+     * @param sessions either <code>null</code> or all unexpired sessions
+     *        associated with the principal
      * @param allowableSessions DOCUMENT ME!
-     * @param registry          an instance of the <code>SessionRegistry</code> for
-     *                          subclass use
+     * @param registry an instance of the <code>SessionRegistry</code> for
+     *        subclass use
+     *
      * @throws ConcurrentLoginException DOCUMENT ME!
      */
     protected void allowableSessionsExceeded(String sessionId,
-                                             SessionInformation[] sessions, int allowableSessions,
-                                             SessionRegistry registry) {
+        SessionInformation[] sessions, int allowableSessions,
+        SessionRegistry registry) {
         if (exceptionIfMaximumExceeded || (sessions == null)) {
             throw new ConcurrentLoginException(messages.getMessage(
                     "ConcurrentSessionControllerImpl.exceededAllowed",
-                    new Object[]{new Integer(allowableSessions)},
+                    new Object[] {new Integer(allowableSessions)},
                     "Maximum sessions of {0} for this principal exceeded"));
         }
 
@@ -82,8 +88,8 @@ public class ConcurrentSessionControllerImpl implements ConcurrentSessionControl
 
         for (int i = 0; i < sessions.length; i++) {
             if ((leastRecentlyUsed == null)
-                    || sessions[i].getLastRequest()
-                    .before(leastRecentlyUsed.getLastRequest())) {
+                || sessions[i].getLastRequest()
+                              .before(leastRecentlyUsed.getLastRequest())) {
                 leastRecentlyUsed = sessions[i];
             }
         }
@@ -92,16 +98,17 @@ public class ConcurrentSessionControllerImpl implements ConcurrentSessionControl
     }
 
     public void checkAuthenticationAllowed(Authentication request)
-            throws AuthenticationException {
+        throws AuthenticationException {
         Assert.notNull(request,
-                "Authentication request cannot be null (violation of interface contract)");
+            "Authentication request cannot be null (violation of interface contract)");
 
         Object principal = SessionRegistryUtils
-                .obtainPrincipalFromAuthentication(request);
+            .obtainPrincipalFromAuthentication(request);
         String sessionId = SessionRegistryUtils
-                .obtainSessionIdFromAuthentication(request);
+            .obtainSessionIdFromAuthentication(request);
 
-        SessionInformation[] sessions = sessionRegistry.getAllSessions(principal);
+        SessionInformation[] sessions = sessionRegistry.getAllSessions(principal,
+                false);
 
         int sessionCount = 0;
 
@@ -111,7 +118,7 @@ public class ConcurrentSessionControllerImpl implements ConcurrentSessionControl
 
         int allowableSessions = getMaximumSessionsForThisUser(request);
         Assert.isTrue(allowableSessions != 0,
-                "getMaximumSessionsForThisUser() must return either -1 to allow unlimited logins, or a positive integer to specify a maximum");
+            "getMaximumSessionsForThisUser() must return either -1 to allow unlimited logins, or a positive integer to specify a maximum");
 
         if (sessionCount < allowableSessions) {
             return;
@@ -124,41 +131,40 @@ public class ConcurrentSessionControllerImpl implements ConcurrentSessionControl
             }
         }
 
-        allowableSessionsExceeded(sessionId, sessions,
-                allowableSessions, sessionRegistry);
+        allowableSessionsExceeded(sessionId, sessions, allowableSessions,
+            sessionRegistry);
     }
 
     /**
-     * Method intended for use by subclasses to override the maximum
-     * number of sessions that are permitted for a particular
-     * authentication. The default implementation simply returns the
-     * <code>maximumSessions</code> value for the bean.
+     * Method intended for use by subclasses to override the maximum number of
+     * sessions that are permitted for a particular authentication. The
+     * default implementation simply returns the <code>maximumSessions</code>
+     * value for the bean.
      *
      * @param authentication to determine the maximum sessions for
-     * @return either -1 meaning unlimited, or a positive integer to
-     *         limit (never zero)
+     *
+     * @return either -1 meaning unlimited, or a positive integer to limit
+     *         (never zero)
      */
-    protected int getMaximumSessionsForThisUser(
-            Authentication authentication) {
+    protected int getMaximumSessionsForThisUser(Authentication authentication) {
         return maximumSessions;
     }
 
-    public void registerSuccessfulAuthentication(
-            Authentication authentication) {
+    public void registerSuccessfulAuthentication(Authentication authentication) {
         Assert.notNull(authentication,
-                "Authentication cannot be null (violation of interface contract)");
+            "Authentication cannot be null (violation of interface contract)");
 
         Object principal = SessionRegistryUtils
-                .obtainPrincipalFromAuthentication(authentication);
+            .obtainPrincipalFromAuthentication(authentication);
         String sessionId = SessionRegistryUtils
-                .obtainSessionIdFromAuthentication(authentication);
+            .obtainSessionIdFromAuthentication(authentication);
 
         sessionRegistry.removeSessionInformation(sessionId);
         sessionRegistry.registerNewSession(sessionId, principal);
     }
 
     public void setExceptionIfMaximumExceeded(
-            boolean exceptionIfMaximumExceeded) {
+        boolean exceptionIfMaximumExceeded) {
         this.exceptionIfMaximumExceeded = exceptionIfMaximumExceeded;
     }
 
@@ -170,8 +176,7 @@ public class ConcurrentSessionControllerImpl implements ConcurrentSessionControl
         this.messages = new MessageSourceAccessor(messageSource);
     }
 
-    public void setSessionRegistry(
-            SessionRegistry sessionRegistry) {
+    public void setSessionRegistry(SessionRegistry sessionRegistry) {
         this.sessionRegistry = sessionRegistry;
     }
 }

+ 9 - 4
core/src/main/java/org/acegisecurity/concurrent/SessionRegistry.java

@@ -34,15 +34,20 @@ public interface SessionRegistry {
 
     /**
      * Obtains all the known sessions for the specified principal. Sessions
-     * that have expired or destroyed are not returned.
+     * that have been destroyed are not returned. Sessions that have expired
+     * may be returned, depending on the passed argument.
      *
      * @param principal to locate sessions for (should never be
      *        <code>null</code>)
+     * @param includeExpiredSessions if <code>true</code>, the returned
+     *        sessions will also include those that have expired for the
+     *        principal
      *
-     * @return the unexpired and undestroyed sessions for this principal, or
-     *         <code>null</code> if none were found
+     * @return the matching sessions for this principal, or <code>null</code>
+     *         if none were found
      */
-    public SessionInformation[] getAllSessions(Object principal);
+    public SessionInformation[] getAllSessions(Object principal,
+        boolean includeExpiredSessions);
 
     /**
      * Obtains the session information for the specified

+ 3 - 2
core/src/main/java/org/acegisecurity/concurrent/SessionRegistryImpl.java

@@ -64,7 +64,8 @@ public class SessionRegistryImpl implements SessionRegistry,
         return principals.keySet().toArray();
     }
 
-    public SessionInformation[] getAllSessions(Object principal) {
+    public SessionInformation[] getAllSessions(Object principal,
+        boolean includeExpiredSessions) {
         Set sessionsUsedByPrincipal = (Set) principals.get(principal);
 
         if (sessionsUsedByPrincipal == null) {
@@ -79,7 +80,7 @@ public class SessionRegistryImpl implements SessionRegistry,
                 String sessionId = (String) iter.next();
                 SessionInformation sessionInformation = getSessionInformation(sessionId);
 
-                if (!sessionInformation.isExpired()) {
+                if (includeExpiredSessions || !sessionInformation.isExpired()) {
                     list.add(sessionInformation);
                 }
             }