Ver Fonte

Refactoring of ProviderManager to ensure that any AuthenticationException from the ConcurrentSessionController will prevent further polling of providers.

Luke Taylor há 16 anos atrás
pai
commit
8a3930e673

+ 21 - 14
core/src/main/java/org/springframework/security/authentication/ProviderManager.java

@@ -170,27 +170,34 @@ public class ProviderManager extends AbstractAuthenticationManager implements In
             try {
                 result = provider.authenticate(authentication);
 
-                if (result != null) {
-                    copyDetails(authentication, result);
-                    sessionController.checkAuthenticationAllowed(result);
+                if (result == null) {
+                    continue;
                 }
-            } catch (AuthenticationException ae) {
-                lastException = ae;
-                result = null;
+            } catch (AccountStatusException e) {
+                // SEC-546: Avoid polling additional providers if auth failure is due to invalid account status
+                lastException = e;
+                break;
+            } catch (AuthenticationException e) {
+                lastException = e;
+                continue;
             }
 
-            // SEC-546: Avoid polling additional providers if auth failure is due to invalid account status or
-            // disallowed concurrent login.
-            if (lastException instanceof AccountStatusException || lastException instanceof ConcurrentLoginException) {
+            assert result != null;
+
+            copyDetails(authentication, result);
+
+            try {
+                sessionController.checkAuthenticationAllowed(result);
+            } catch (AuthenticationException e) {
+             // SEC-546: Avoid polling additional providers if concurrent login check fails
+                lastException = e;
                 break;
             }
 
-            if (result != null) {
-                sessionController.registerSuccessfulAuthentication(result);
-                publishEvent(new AuthenticationSuccessEvent(result));
+            sessionController.registerSuccessfulAuthentication(result);
+            publishEvent(new AuthenticationSuccessEvent(result));
 
-                return result;
-            }
+            return result;
         }
 
         if (lastException == null) {

+ 8 - 7
core/src/test/java/org/springframework/security/authentication/ProviderManagerTests.java

@@ -16,7 +16,7 @@
 package org.springframework.security.authentication;
 
 import static org.junit.Assert.*;
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.*;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -45,8 +45,6 @@ import org.springframework.security.core.authority.AuthorityUtils;
  */
 public class ProviderManagerTests {
 
-    //~ Methods ========================================================================================================
-
     @Test(expected=ProviderNotFoundException.class)
     public void authenticationFailsWithUnsupportedToken() throws Exception {
         UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test", "Password",
@@ -185,11 +183,14 @@ public class ProviderManagerTests {
     @Test(expected=ConcurrentLoginException.class)
     public void concurrentLoginExceptionPreventsCallsToSubsequentProviders() throws Exception {
         ProviderManager authMgr = makeProviderManager();
+        // Two providers so if the second is polled it will throw an AccountStatusException
+        authMgr.setProviders(Arrays.asList(new MockProvider(), new MockProviderWhichThrowsAccountStatusException()) );
+        TestingAuthenticationToken request = createAuthenticationToken();
+        ConcurrentSessionController ctrlr = mock(ConcurrentSessionController.class);
+        doThrow(new ConcurrentLoginException("mocked")).when(ctrlr).checkAuthenticationAllowed(request);
+        authMgr.setSessionController(ctrlr);
 
-        authMgr.setProviders(Arrays.asList(new MockProviderWhichThrowsConcurrentLoginException(),
-                new MockProviderWhichThrowsAccountStatusException()) );
-
-        authMgr.authenticate(createAuthenticationToken());
+        authMgr.authenticate(request);
     }
 
     private TestingAuthenticationToken createAuthenticationToken() {