Browse Source

SEC-7: Allow better chaining of authentication providers.

Ben Alex 20 years ago
parent
commit
2cbe42f493
1 changed files with 30 additions and 2 deletions
  1. 30 2
      core/src/main/java/org/acegisecurity/providers/ProviderManager.java

+ 30 - 2
core/src/main/java/org/acegisecurity/providers/ProviderManager.java

@@ -35,6 +35,22 @@ import java.util.List;
  * AuthenticationProvider}s. Can optionally be configured with a {@link
  * ConcurrentSessionController} to limit the number of sessions a user can
  * have.
+ * 
+ * <p>
+ * <code>AuthenticationProvider</code>s are tried in order until one provides a
+ * non-null response. A non-null response indicates the provider had authority
+ * to decide on the authentication request and no further providers are tried.
+ * If an <code>AuthenticationException</code> is thrown by a provider, it is
+ * retained until subsequent providers are tried. If a subsequent provider
+ * successfully authenticates the request, the earlier authentication
+ * exception is disregarded and the successful authentication will be used. If
+ * no subsequent provider provides a non-null response, or a new
+ * <code>AuthenticationException</code>, the last
+ * <code>AuthenticationException</code> received will be used. If no provider
+ * returns a non-null response, or indicates it can even process an
+ * <code>Authentication</code>, the <code>ProviderManager</code> will throw a
+ * <code>ProviderNotFoundException</code>.
+ * </p>
  *
  * @author Ben Alex
  * @author Wesley Hall
@@ -107,7 +123,7 @@ public class ProviderManager extends AbstractAuthenticationManager
      * {@link NullConcurrentSessionController} if a specific one has not been
      * set.
      *
-     * @return{@link ConcurrentSessionController} instance
+     * @return {@link ConcurrentSessionController} instance
      */
     public ConcurrentSessionController getSessionController() {
         return sessionController;
@@ -150,6 +166,8 @@ public class ProviderManager extends AbstractAuthenticationManager
 
         sessionController.checkAuthenticationAllowed(authentication);
 
+        AuthenticationException lastException = null;
+
         while (iter.hasNext()) {
             AuthenticationProvider provider = (AuthenticationProvider) iter
                 .next();
@@ -158,7 +176,13 @@ public class ProviderManager extends AbstractAuthenticationManager
                 logger.debug("Authentication attempt using "
                     + provider.getClass().getName());
 
-                Authentication result = provider.authenticate(authentication);
+                Authentication result = null;
+
+                try {
+                    result = provider.authenticate(authentication);
+                } catch (AuthenticationException ae) {
+                    lastException = ae;
+                }
 
                 if (result != null) {
                     sessionController.registerSuccessfulAuthentication(result);
@@ -168,6 +192,10 @@ public class ProviderManager extends AbstractAuthenticationManager
             }
         }
 
+        if (lastException != null) {
+            throw lastException;
+        }
+
         throw new ProviderNotFoundException("No authentication provider for "
             + toTest.getName());
     }