diff --git a/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java b/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java index bb03b6e3cb..2296f21f5d 100644 --- a/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java +++ b/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java @@ -23,11 +23,13 @@ import net.sf.acegisecurity.BadCredentialsException; import net.sf.acegisecurity.CredentialsExpiredException; import net.sf.acegisecurity.DisabledException; import net.sf.acegisecurity.GrantedAuthority; +import net.sf.acegisecurity.LockedException; import net.sf.acegisecurity.UserDetails; import net.sf.acegisecurity.providers.AuthenticationProvider; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; import net.sf.acegisecurity.providers.dao.cache.NullUserCache; import net.sf.acegisecurity.providers.dao.event.AuthenticationFailureAccountExpiredEvent; +import net.sf.acegisecurity.providers.dao.event.AuthenticationFailureAccountLockedEvent; import net.sf.acegisecurity.providers.dao.event.AuthenticationFailureCredentialsExpiredEvent; import net.sf.acegisecurity.providers.dao.event.AuthenticationFailureDisabledEvent; import net.sf.acegisecurity.providers.dao.event.AuthenticationFailurePasswordEvent; @@ -232,7 +234,8 @@ public class DaoAuthenticationProvider implements AuthenticationProvider, authentication, new User("".equals(username) ? "EMPTY_STRING_PROVIDED" : username, "*****", - false, false, false, new GrantedAuthority[0]))); + false, false, false, false, + new GrantedAuthority[0]))); } throw ex; @@ -257,6 +260,15 @@ public class DaoAuthenticationProvider implements AuthenticationProvider, throw new AccountExpiredException("User account has expired"); } + if (!user.isAccountNonLocked()) { + if (this.context != null) { + context.publishEvent(new AuthenticationFailureAccountLockedEvent( + authentication, user)); + } + + throw new LockedException("User account is locked"); + } + if (!user.isCredentialsNonExpired()) { if (this.context != null) { context.publishEvent(new AuthenticationFailureCredentialsExpiredEvent( diff --git a/core/src/main/java/org/acegisecurity/providers/dao/PasswordDaoAuthenticationProvider.java b/core/src/main/java/org/acegisecurity/providers/dao/PasswordDaoAuthenticationProvider.java index 943e96a07d..57c3d38833 100644 --- a/core/src/main/java/org/acegisecurity/providers/dao/PasswordDaoAuthenticationProvider.java +++ b/core/src/main/java/org/acegisecurity/providers/dao/PasswordDaoAuthenticationProvider.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -23,11 +23,13 @@ import net.sf.acegisecurity.BadCredentialsException; import net.sf.acegisecurity.CredentialsExpiredException; import net.sf.acegisecurity.DisabledException; import net.sf.acegisecurity.GrantedAuthority; +import net.sf.acegisecurity.LockedException; import net.sf.acegisecurity.UserDetails; import net.sf.acegisecurity.providers.AuthenticationProvider; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; import net.sf.acegisecurity.providers.dao.cache.NullUserCache; import net.sf.acegisecurity.providers.dao.event.AuthenticationFailureAccountExpiredEvent; +import net.sf.acegisecurity.providers.dao.event.AuthenticationFailureAccountLockedEvent; import net.sf.acegisecurity.providers.dao.event.AuthenticationFailureCredentialsExpiredEvent; import net.sf.acegisecurity.providers.dao.event.AuthenticationFailureDisabledEvent; import net.sf.acegisecurity.providers.dao.event.AuthenticationFailureUsernameOrPasswordEvent; @@ -184,7 +186,7 @@ public class PasswordDaoAuthenticationProvider implements AuthenticationProvider context.publishEvent(new AuthenticationFailureUsernameOrPasswordEvent( authentication, new User(username, "*****", false, false, false, - new GrantedAuthority[0]))); + false, new GrantedAuthority[0]))); } throw ex; @@ -209,6 +211,15 @@ public class PasswordDaoAuthenticationProvider implements AuthenticationProvider throw new AccountExpiredException("User account has expired"); } + if (!user.isAccountNonLocked()) { + if (this.context != null) { + context.publishEvent(new AuthenticationFailureAccountLockedEvent( + authentication, user)); + } + + throw new LockedException("User account is locked"); + } + if (!user.isCredentialsNonExpired()) { if (this.context != null) { context.publishEvent(new AuthenticationFailureCredentialsExpiredEvent( diff --git a/core/src/main/java/org/acegisecurity/providers/dao/event/AuthenticationFailureAccountLockedEvent.java b/core/src/main/java/org/acegisecurity/providers/dao/event/AuthenticationFailureAccountLockedEvent.java new file mode 100644 index 0000000000..c239a59583 --- /dev/null +++ b/core/src/main/java/org/acegisecurity/providers/dao/event/AuthenticationFailureAccountLockedEvent.java @@ -0,0 +1,36 @@ +/* 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.dao.event; + +import net.sf.acegisecurity.Authentication; +import net.sf.acegisecurity.UserDetails; + + +/** + * Application event which indicates authentication failure due to the user's + * account having been locked. + * + * @author Ben Alex + * @version $Id$ + */ +public class AuthenticationFailureAccountLockedEvent extends AuthenticationEvent { + //~ Constructors =========================================================== + + public AuthenticationFailureAccountLockedEvent( + Authentication authentication, UserDetails user) { + super(authentication, user); + } +} diff --git a/core/src/main/java/org/acegisecurity/providers/dao/event/LoggerListener.java b/core/src/main/java/org/acegisecurity/providers/dao/event/LoggerListener.java index 2cd0ec9cad..90d72ebb40 100644 --- a/core/src/main/java/org/acegisecurity/providers/dao/event/LoggerListener.java +++ b/core/src/main/java/org/acegisecurity/providers/dao/event/LoggerListener.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -63,6 +63,17 @@ public class LoggerListener implements ApplicationListener { } } + if (event instanceof AuthenticationFailureAccountLockedEvent) { + AuthenticationFailureAccountLockedEvent authEvent = (AuthenticationFailureAccountLockedEvent) event; + + if (logger.isWarnEnabled()) { + logger.warn( + "Authentication failed due to account being locked for user: " + + authEvent.getUser().getUsername() + "; details: " + + authEvent.getAuthentication().getDetails()); + } + } + if (event instanceof AuthenticationFailureCredentialsExpiredEvent) { AuthenticationFailureCredentialsExpiredEvent authEvent = (AuthenticationFailureCredentialsExpiredEvent) event; diff --git a/core/src/main/java/org/acegisecurity/userdetails/User.java b/core/src/main/java/org/acegisecurity/userdetails/User.java index ba8ac3ef30..64c7333c51 100644 --- a/core/src/main/java/org/acegisecurity/userdetails/User.java +++ b/core/src/main/java/org/acegisecurity/userdetails/User.java @@ -38,6 +38,7 @@ public class User implements UserDetails { private String username; private GrantedAuthority[] authorities; private boolean accountNonExpired; + private boolean accountNonLocked; private boolean credentialsNonExpired; private boolean enabled; @@ -88,10 +89,44 @@ public class User implements UserDetails { * @throws IllegalArgumentException if a null value was passed * either as a parameter or as an element in the * GrantedAuthority[] array + * + * @deprecated use new constructor with extended properties (this + * constructor will be removed from release 1.0.0) */ public User(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, GrantedAuthority[] authorities) throws IllegalArgumentException { + this(username, password, enabled, accountNonExpired, + credentialsNonExpired, true, authorities); + } + + /** + * Construct the User with the details required by {@link + * DaoAuthenticationProvider}. + * + * @param username the username presented to the + * DaoAuthenticationProvider + * @param password the password that should be presented to the + * DaoAuthenticationProvider + * @param enabled set to true if the user is enabled + * @param accountNonExpired set to true if the account has not + * expired + * @param credentialsNonExpired set to true if the credentials + * have not expired + * @param accountNonLocked set to true if the account is not + * locked + * @param authorities the authorities that should be granted to the caller + * if they presented the correct username and password and the user + * is enabled + * + * @throws IllegalArgumentException if a null value was passed + * either as a parameter or as an element in the + * GrantedAuthority[] array + */ + public User(String username, String password, boolean enabled, + boolean accountNonExpired, boolean credentialsNonExpired, + boolean accountNonLocked, GrantedAuthority[] authorities) + throws IllegalArgumentException { if (((username == null) || "".equals(username)) || (password == null) || (authorities == null)) { throw new IllegalArgumentException( @@ -112,6 +147,7 @@ public class User implements UserDetails { this.authorities = authorities; this.accountNonExpired = accountNonExpired; this.credentialsNonExpired = credentialsNonExpired; + this.accountNonLocked = accountNonLocked; } protected User() { @@ -124,6 +160,10 @@ public class User implements UserDetails { return accountNonExpired; } + public boolean isAccountNonLocked() { + return this.accountNonLocked; + } + public GrantedAuthority[] getAuthorities() { return authorities; } diff --git a/core/src/main/java/org/acegisecurity/userdetails/UserDetails.java b/core/src/main/java/org/acegisecurity/userdetails/UserDetails.java index 93bfe58929..e8f8ffc3cb 100644 --- a/core/src/main/java/org/acegisecurity/userdetails/UserDetails.java +++ b/core/src/main/java/org/acegisecurity/userdetails/UserDetails.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -53,6 +53,15 @@ public interface UserDetails extends Serializable { */ public boolean isAccountNonExpired(); + /** + * Indicates whether the user is locked or unlocked. A locked user cannot + * be authenticated. + * + * @return true if the user is not locked, false + * otherwise + */ + public boolean isAccountNonLocked(); + /** * Returns the authorities granted to the user. Cannot return * null. diff --git a/core/src/main/java/org/acegisecurity/userdetails/jdbc/JdbcDaoImpl.java b/core/src/main/java/org/acegisecurity/userdetails/jdbc/JdbcDaoImpl.java index 0dc668bbad..76da5d3e54 100644 --- a/core/src/main/java/org/acegisecurity/userdetails/jdbc/JdbcDaoImpl.java +++ b/core/src/main/java/org/acegisecurity/userdetails/jdbc/JdbcDaoImpl.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -192,7 +192,7 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements AuthenticationDao { arrayAuths = (GrantedAuthority[]) dbAuths.toArray(arrayAuths); return new User(user.getUsername(), user.getPassword(), - user.isEnabled(), true, true, arrayAuths); + user.isEnabled(), true, true, true, arrayAuths); } /** @@ -256,7 +256,7 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements AuthenticationDao { String password = rs.getString(2); boolean enabled = rs.getBoolean(3); UserDetails user = new User(username, password, enabled, true, - true, + true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")}); return user; diff --git a/core/src/main/java/org/acegisecurity/userdetails/memory/UserMapEditor.java b/core/src/main/java/org/acegisecurity/userdetails/memory/UserMapEditor.java index b7a97f7149..834847436b 100644 --- a/core/src/main/java/org/acegisecurity/userdetails/memory/UserMapEditor.java +++ b/core/src/main/java/org/acegisecurity/userdetails/memory/UserMapEditor.java @@ -96,7 +96,8 @@ public class UserMapEditor extends PropertyEditorSupport { // Make a user object, assuming the properties were properly provided if (attr != null) { UserDetails user = new User(username, attr.getPassword(), - attr.isEnabled(), true, true, attr.getAuthorities()); + attr.isEnabled(), true, true, true, + attr.getAuthorities()); userMap.addUser(user); } } diff --git a/core/src/test/java/org/acegisecurity/acl/basic/GrantedAuthorityEffectiveAclsResolverTests.java b/core/src/test/java/org/acegisecurity/acl/basic/GrantedAuthorityEffectiveAclsResolverTests.java index 5e856f0eb9..0477d11fae 100644 --- a/core/src/test/java/org/acegisecurity/acl/basic/GrantedAuthorityEffectiveAclsResolverTests.java +++ b/core/src/test/java/org/acegisecurity/acl/basic/GrantedAuthorityEffectiveAclsResolverTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -55,7 +55,7 @@ public class GrantedAuthorityEffectiveAclsResolverTests extends TestCase { .getPrincipal(), new NamedEntityObjectIdentity("OBJECT", "100"), null, 2); private UsernamePasswordAuthenticationToken scottWithUserDetails = new UsernamePasswordAuthenticationToken(new User( - "scott", "NOT_USED", true, true, true, + "scott", "NOT_USED", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl( "ROLE_EVERYBODY")}), "not used", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_EVERYBODY"), new GrantedAuthorityImpl("ROLE_TWO")}); diff --git a/core/src/test/java/org/acegisecurity/providers/ConcurrentSessionControllerImplTests.java b/core/src/test/java/org/acegisecurity/providers/ConcurrentSessionControllerImplTests.java index 5703ce31d3..d1d459489c 100644 --- a/core/src/test/java/org/acegisecurity/providers/ConcurrentSessionControllerImplTests.java +++ b/core/src/test/java/org/acegisecurity/providers/ConcurrentSessionControllerImplTests.java @@ -16,12 +16,14 @@ package net.sf.acegisecurity.providers; import junit.framework.TestCase; + import net.sf.acegisecurity.*; import net.sf.acegisecurity.providers.anonymous.AnonymousAuthenticationToken; import net.sf.acegisecurity.providers.dao.User; import net.sf.acegisecurity.ui.WebAuthenticationDetails; import net.sf.acegisecurity.ui.session.HttpSessionCreatedEvent; import net.sf.acegisecurity.ui.session.HttpSessionDestroyedEvent; + import org.springframework.context.ApplicationListener; import java.security.Principal; @@ -39,8 +41,17 @@ public class ConcurrentSessionControllerImplTests extends TestCase { //~ Methods ================================================================ + public void testAnonymous() throws Exception { + AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken("blah", + "anon", + new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ANON")}); + target.beforeAuthentication(auth); + target.afterAuthentication(auth, auth); + } + public void testBumpCoverage() throws Exception { - target.onApplicationEvent(new HttpSessionCreatedEvent(new MockHttpSession())); + target.onApplicationEvent(new HttpSessionCreatedEvent( + new MockHttpSession())); } public void testEnforcementKnownGood() throws Exception { @@ -63,7 +74,8 @@ public class ConcurrentSessionControllerImplTests extends TestCase { try { auth = createAuthentication("user", "password", "lastsession"); target.beforeAuthentication(auth); - fail("Only allowed 5 sessions, this should have thrown a ConcurrentLoginException"); + fail( + "Only allowed 5 sessions, this should have thrown a ConcurrentLoginException"); } catch (ConcurrentLoginException e) { assertTrue(e.getMessage().startsWith(auth.getPrincipal().toString())); } @@ -81,9 +93,9 @@ public class ConcurrentSessionControllerImplTests extends TestCase { try { target.beforeAuthentication(createAuthentication("user", "password", "session2")); - fail("Only allowed 1 session, this should have thrown a ConcurrentLoginException"); - } catch (ConcurrentLoginException e) { - } + fail( + "Only allowed 1 session, this should have thrown a ConcurrentLoginException"); + } catch (ConcurrentLoginException e) {} } public void testEnforcementUnlimitedSameSession() throws Exception { @@ -129,6 +141,11 @@ public class ConcurrentSessionControllerImplTests extends TestCase { target.afterAuthentication(different, different); } + public void testImplementsApplicationListener() throws Exception { + assertTrue("This class must implement ApplicationListener, and at one point it didn't.", + target instanceof ApplicationListener); + } + public void testNonWebDetails() throws Exception { UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("asdf", "asdf"); @@ -141,7 +158,7 @@ public class ConcurrentSessionControllerImplTests extends TestCase { target.setMaxSessions(1); final UserDetails user = new User("user", "password", true, true, true, - new GrantedAuthority[0]); + true, new GrantedAuthority[0]); final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, "password", user.getAuthorities()); auth.setDetails(createWebDetails(auth, "session1")); @@ -151,20 +168,20 @@ public class ConcurrentSessionControllerImplTests extends TestCase { try { UsernamePasswordAuthenticationToken otherAuth = new UsernamePasswordAuthenticationToken(new Principal() { - public String getName() { - return "user"; - } + public String getName() { + return "user"; + } - public String toString() { - return getName(); - } - }, "password"); + public String toString() { + return getName(); + } + }, "password"); otherAuth.setDetails(createWebDetails(otherAuth, "session2")); target.beforeAuthentication(otherAuth); - fail("Same principal, different principal type, different session should have thrown ConcurrentLoginException"); - } catch (ConcurrentLoginException e) { - } + fail( + "Same principal, different principal type, different session should have thrown ConcurrentLoginException"); + } catch (ConcurrentLoginException e) {} } public void testSetMax() throws Exception { @@ -177,7 +194,7 @@ public class ConcurrentSessionControllerImplTests extends TestCase { public void testSetTrustManager() throws Exception { assertNotNull("There is supposed to be a default AuthenticationTrustResolver", - target.getTrustResolver()); + target.getTrustResolver()); AuthenticationTrustResolverImpl impl = new AuthenticationTrustResolverImpl(); target.setTrustResolver(impl); @@ -220,7 +237,7 @@ public class ConcurrentSessionControllerImplTests extends TestCase { } private Authentication createAuthentication(String user, String password, - String sessionId) { + String sessionId) { UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, password); auth.setDetails(createWebDetails(auth, sessionId)); @@ -229,21 +246,11 @@ public class ConcurrentSessionControllerImplTests extends TestCase { } private WebAuthenticationDetails createWebDetails(Authentication auth, - String sessionId) { + String sessionId) { MockHttpSession session = new MockHttpSession(sessionId); MockHttpServletRequest request = new MockHttpServletRequest(auth, session); return new WebAuthenticationDetails(request); } - - public void testAnonymous() throws Exception { - AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken("blah", "anon", new GrantedAuthority[]{new GrantedAuthorityImpl("ROLE_ANON")}); - target.beforeAuthentication(auth); - target.afterAuthentication(auth, auth); - } - - public void testImplementsApplicationListener() throws Exception { - assertTrue("This class must implement ApplicationListener, and at one point it didn't.", target instanceof ApplicationListener); - } } diff --git a/core/src/test/java/org/acegisecurity/providers/cas/CasAuthenticationProviderTests.java b/core/src/test/java/org/acegisecurity/providers/cas/CasAuthenticationProviderTests.java index 3a3dcaa6e1..c92158edf4 100644 --- a/core/src/test/java/org/acegisecurity/providers/cas/CasAuthenticationProviderTests.java +++ b/core/src/test/java/org/acegisecurity/providers/cas/CasAuthenticationProviderTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -327,7 +327,7 @@ public class CasAuthenticationProviderTests extends TestCase { } private UserDetails makeUserDetails() { - return new User("user", "password", true, true, true, + return new User("user", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); } @@ -337,7 +337,7 @@ public class CasAuthenticationProviderTests extends TestCase { private class MockAuthoritiesPopulator implements CasAuthoritiesPopulator { public UserDetails getUserDetails(String casUserId) throws AuthenticationException { - return new User("user", "password", true, true, true, + return new User("user", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A"), new GrantedAuthorityImpl( "ROLE_B")}); } diff --git a/core/src/test/java/org/acegisecurity/providers/cas/CasAuthenticationTokenTests.java b/core/src/test/java/org/acegisecurity/providers/cas/CasAuthenticationTokenTests.java index f1af3dc848..09e3dccd05 100644 --- a/core/src/test/java/org/acegisecurity/providers/cas/CasAuthenticationTokenTests.java +++ b/core/src/test/java/org/acegisecurity/providers/cas/CasAuthenticationTokenTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -319,7 +319,7 @@ public class CasAuthenticationTokenTests extends TestCase { } private UserDetails makeUserDetails() { - return new User("user", "password", true, true, true, + return new User("user", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); } diff --git a/core/src/test/java/org/acegisecurity/providers/cas/cache/EhCacheBasedTicketCacheTests.java b/core/src/test/java/org/acegisecurity/providers/cas/cache/EhCacheBasedTicketCacheTests.java index 57a797252e..d077a5d51a 100644 --- a/core/src/test/java/org/acegisecurity/providers/cas/cache/EhCacheBasedTicketCacheTests.java +++ b/core/src/test/java/org/acegisecurity/providers/cas/cache/EhCacheBasedTicketCacheTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -102,7 +102,7 @@ public class EhCacheBasedTicketCacheTests extends TestCase { List proxyList = new Vector(); proxyList.add("https://localhost/newPortal/j_acegi_cas_security_check"); - User user = new User("marissa", "password", true, true, true, + User user = new User("marissa", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); diff --git a/core/src/test/java/org/acegisecurity/providers/cas/populator/DaoCasAuthoritiesPopulatorTests.java b/core/src/test/java/org/acegisecurity/providers/cas/populator/DaoCasAuthoritiesPopulatorTests.java index 304e2397d1..250b5dfc45 100644 --- a/core/src/test/java/org/acegisecurity/providers/cas/populator/DaoCasAuthoritiesPopulatorTests.java +++ b/core/src/test/java/org/acegisecurity/providers/cas/populator/DaoCasAuthoritiesPopulatorTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -139,7 +139,7 @@ public class DaoCasAuthoritiesPopulatorTests extends TestCase { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("marissa".equals(username)) { - return new User("marissa", "koala", true, true, true, + return new User("marissa", "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); } else { diff --git a/core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationProviderTests.java b/core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationProviderTests.java index d9c00f850d..40281275df 100644 --- a/core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationProviderTests.java +++ b/core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationProviderTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -25,6 +25,7 @@ import net.sf.acegisecurity.CredentialsExpiredException; import net.sf.acegisecurity.DisabledException; import net.sf.acegisecurity.GrantedAuthority; import net.sf.acegisecurity.GrantedAuthorityImpl; +import net.sf.acegisecurity.LockedException; import net.sf.acegisecurity.UserDetails; import net.sf.acegisecurity.providers.TestingAuthenticationToken; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; @@ -103,6 +104,32 @@ public class DaoAuthenticationProviderTests extends TestCase { } } + public void testAuthenticateFailsIfAccountLocked() { + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", + "opal"); + + DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); + provider.setAuthenticationDao(new MockAuthenticationDaoUserPeterAccountLocked()); + provider.setUserCache(new MockUserCache()); + + try { + provider.authenticate(token); + fail("Should have thrown LockedException"); + } catch (LockedException expected) { + assertTrue(true); + } + + provider.setApplicationContext(new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/util/filtertest-valid.xml")); + + try { + provider.authenticate(token); + fail("Should have thrown CredentialsExpiredException"); + } catch (LockedException expected) { + assertTrue(true); + } + } + public void testAuthenticateFailsIfCredentialsExpired() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal"); @@ -492,7 +519,7 @@ public class DaoAuthenticationProviderTests extends TestCase { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("marissa".equals(username)) { - return new User("marissa", password, true, true, true, + return new User("marissa", password, true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); } else { @@ -508,7 +535,7 @@ public class DaoAuthenticationProviderTests extends TestCase { throws UsernameNotFoundException, DataAccessException { if ("marissa".equals(username)) { return new User("marissa", "koala{SYSTEM_SALT_VALUE}", true, - true, true, + true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); } else { @@ -522,7 +549,7 @@ public class DaoAuthenticationProviderTests extends TestCase { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("peter".equals(username)) { - return new User("peter", "opal", false, true, true, + return new User("peter", "opal", false, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); } else { @@ -537,7 +564,22 @@ public class DaoAuthenticationProviderTests extends TestCase { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("peter".equals(username)) { - return new User("peter", "opal", true, false, true, + return new User("peter", "opal", true, false, true, true, + new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( + "ROLE_TWO")}); + } else { + throw new UsernameNotFoundException("Could not find: " + + username); + } + } + } + + private class MockAuthenticationDaoUserPeterAccountLocked + implements AuthenticationDao { + public UserDetails loadUserByUsername(String username) + throws UsernameNotFoundException, DataAccessException { + if ("peter".equals(username)) { + return new User("peter", "opal", true, true, true, false, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); } else { @@ -552,7 +594,7 @@ public class DaoAuthenticationProviderTests extends TestCase { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { if ("peter".equals(username)) { - return new User("peter", "opal", true, true, false, + return new User("peter", "opal", true, true, false, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); } else { diff --git a/core/src/test/java/org/acegisecurity/providers/dao/PasswordDaoAuthenticationProviderTests.java b/core/src/test/java/org/acegisecurity/providers/dao/PasswordDaoAuthenticationProviderTests.java index e0b33b84e3..6bdd2618da 100644 --- a/core/src/test/java/org/acegisecurity/providers/dao/PasswordDaoAuthenticationProviderTests.java +++ b/core/src/test/java/org/acegisecurity/providers/dao/PasswordDaoAuthenticationProviderTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -25,6 +25,7 @@ import net.sf.acegisecurity.CredentialsExpiredException; import net.sf.acegisecurity.DisabledException; import net.sf.acegisecurity.GrantedAuthority; import net.sf.acegisecurity.GrantedAuthorityImpl; +import net.sf.acegisecurity.LockedException; import net.sf.acegisecurity.UserDetails; import net.sf.acegisecurity.providers.TestingAuthenticationToken; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; @@ -98,6 +99,32 @@ public class PasswordDaoAuthenticationProviderTests extends TestCase { } } + public void testAuthenticateFailsIfAccountLocked() { + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", + "opal"); + + PasswordDaoAuthenticationProvider provider = new PasswordDaoAuthenticationProvider(); + provider.setPasswordAuthenticationDao(new MockAuthenticationDaoUserPeterAccountLocked()); + provider.setUserCache(new MockUserCache()); + + try { + provider.authenticate(token); + fail("Should have thrown AccountExpiredException"); + } catch (LockedException expected) { + assertTrue(true); + } + + provider.setApplicationContext(new ClassPathXmlApplicationContext( + "net/sf/acegisecurity/util/filtertest-valid.xml")); + + try { + provider.authenticate(token); + fail("Should have thrown AccountExpiredException"); + } catch (LockedException expected) { + assertTrue(true); + } + } + public void testAuthenticateFailsIfCredentialsExpired() { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal"); @@ -346,7 +373,7 @@ public class PasswordDaoAuthenticationProviderTests extends TestCase { String password) throws BadCredentialsException, DataAccessException { if ("marissa".equals(username) && "koala".equals(password)) { - return new User("marissa", "koala", true, true, true, + return new User("marissa", "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); } else { @@ -361,7 +388,7 @@ public class PasswordDaoAuthenticationProviderTests extends TestCase { String password) throws BadCredentialsException, DataAccessException { if ("peter".equals(username) && "opal".equals(password)) { - return new User("peter", "opal", false, true, true, + return new User("peter", "opal", false, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); } else { @@ -376,7 +403,23 @@ public class PasswordDaoAuthenticationProviderTests extends TestCase { String password) throws UsernameNotFoundException, DataAccessException { if ("peter".equals(username)) { - return new User("peter", "opal", true, false, true, + return new User("peter", "opal", true, false, true, true, + new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( + "ROLE_TWO")}); + } else { + throw new UsernameNotFoundException("Could not find: " + + username); + } + } + } + + private class MockAuthenticationDaoUserPeterAccountLocked + implements PasswordAuthenticationDao { + public UserDetails loadUserByUsernameAndPassword(String username, + String password) + throws UsernameNotFoundException, DataAccessException { + if ("peter".equals(username)) { + return new User("peter", "opal", true, true, true, false, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); } else { @@ -392,7 +435,7 @@ public class PasswordDaoAuthenticationProviderTests extends TestCase { String password) throws UsernameNotFoundException, DataAccessException { if ("peter".equals(username)) { - return new User("peter", "opal", true, true, false, + return new User("peter", "opal", true, true, false, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); } else { diff --git a/core/src/test/java/org/acegisecurity/providers/dao/UserTests.java b/core/src/test/java/org/acegisecurity/providers/dao/UserTests.java index 0a4744508e..fa0ea6b442 100644 --- a/core/src/test/java/org/acegisecurity/providers/dao/UserTests.java +++ b/core/src/test/java/org/acegisecurity/providers/dao/UserTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -60,7 +60,7 @@ public class UserTests extends TestCase { public void testNullValuesRejected() throws Exception { try { - UserDetails user = new User(null, "koala", true, true, true, + UserDetails user = new User(null, "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); fail("Should have thrown IllegalArgumentException"); @@ -70,6 +70,7 @@ public class UserTests extends TestCase { try { UserDetails user = new User("marissa", null, true, true, true, + true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); fail("Should have thrown IllegalArgumentException"); @@ -79,7 +80,7 @@ public class UserTests extends TestCase { try { UserDetails user = new User("marissa", "koala", true, true, true, - null); + true, null); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { assertTrue(true); @@ -87,6 +88,7 @@ public class UserTests extends TestCase { try { UserDetails user = new User("marissa", "koala", true, true, true, + true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), null}); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException expected) { @@ -97,7 +99,7 @@ public class UserTests extends TestCase { public void testNullWithinGrantedAuthorityElementIsRejected() throws Exception { try { - UserDetails user = new User(null, "koala", true, true, true, + UserDetails user = new User(null, "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO"), null, new GrantedAuthorityImpl( "ROLE_THREE")}); @@ -108,7 +110,7 @@ public class UserTests extends TestCase { } public void testUserGettersSetter() throws Exception { - UserDetails user = new User("marissa", "koala", true, true, true, + UserDetails user = new User("marissa", "koala", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); assertEquals("marissa", user.getUsername()); @@ -122,6 +124,7 @@ public class UserTests extends TestCase { public void testUserIsEnabled() throws Exception { UserDetails user = new User("marissa", "koala", false, true, true, + true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); assertTrue(!user.isEnabled()); diff --git a/core/src/test/java/org/acegisecurity/providers/dao/cache/EhCacheBasedUserCacheTests.java b/core/src/test/java/org/acegisecurity/providers/dao/cache/EhCacheBasedUserCacheTests.java index 3367a9e1b0..f2cab603a0 100644 --- a/core/src/test/java/org/acegisecurity/providers/dao/cache/EhCacheBasedUserCacheTests.java +++ b/core/src/test/java/org/acegisecurity/providers/dao/cache/EhCacheBasedUserCacheTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -95,7 +95,7 @@ public class EhCacheBasedUserCacheTests extends TestCase { } private User getUser() { - return new User("john", "password", true, true, true, + return new User("john", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); } diff --git a/core/src/test/java/org/acegisecurity/providers/dao/cache/NullUserCacheTests.java b/core/src/test/java/org/acegisecurity/providers/dao/cache/NullUserCacheTests.java index 920b31a35f..b7e97c083c 100644 --- a/core/src/test/java/org/acegisecurity/providers/dao/cache/NullUserCacheTests.java +++ b/core/src/test/java/org/acegisecurity/providers/dao/cache/NullUserCacheTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -57,7 +57,7 @@ public class NullUserCacheTests extends TestCase { } private User getUser() { - return new User("john", "password", true, true, true, + return new User("john", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); } diff --git a/core/src/test/java/org/acegisecurity/providers/dao/event/AuthenticationEventTests.java b/core/src/test/java/org/acegisecurity/providers/dao/event/AuthenticationEventTests.java index 6cdc804226..be4e52e8ff 100644 --- a/core/src/test/java/org/acegisecurity/providers/dao/event/AuthenticationEventTests.java +++ b/core/src/test/java/org/acegisecurity/providers/dao/event/AuthenticationEventTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -97,7 +97,7 @@ public class AuthenticationEventTests extends TestCase { } private User getUser() { - User user = new User("foo", "bar", true, true, true, + User user = new User("foo", "bar", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_FOOBAR")}); return user; diff --git a/core/src/test/java/org/acegisecurity/providers/dao/event/LoggerListenerTests.java b/core/src/test/java/org/acegisecurity/providers/dao/event/LoggerListenerTests.java index 323c180f29..14d22f480c 100644 --- a/core/src/test/java/org/acegisecurity/providers/dao/event/LoggerListenerTests.java +++ b/core/src/test/java/org/acegisecurity/providers/dao/event/LoggerListenerTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -90,7 +90,7 @@ public class LoggerListenerTests extends TestCase { } private User getUser() { - User user = new User("foo", "bar", true, true, true, + User user = new User("foo", "bar", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_FOOBAR")}); return user; diff --git a/core/src/test/java/org/acegisecurity/providers/dao/memory/UserMapTests.java b/core/src/test/java/org/acegisecurity/providers/dao/memory/UserMapTests.java index 06150601d5..f8aaab20af 100644 --- a/core/src/test/java/org/acegisecurity/providers/dao/memory/UserMapTests.java +++ b/core/src/test/java/org/acegisecurity/providers/dao/memory/UserMapTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -53,12 +53,13 @@ public class UserMapTests extends TestCase { public void testAddAndRetrieveUser() { UserDetails marissa = new User("marissa", "koala", true, true, true, + true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); - UserDetails scott = new User("scott", "wombat", true, true, true, + UserDetails scott = new User("scott", "wombat", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_THREE")}); - UserDetails peter = new User("peter", "opal", true, true, true, + UserDetails peter = new User("peter", "opal", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_FOUR")}); UserMap map = new UserMap(); @@ -86,6 +87,7 @@ public class UserMapTests extends TestCase { public void testUnknownUserIsNotRetrieved() { UserDetails marissa = new User("marissa", "koala", true, true, true, + true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( "ROLE_TWO")}); UserMap map = new UserMap(); diff --git a/core/src/test/java/org/acegisecurity/providers/dao/salt/ReflectionSaltSourceTests.java b/core/src/test/java/org/acegisecurity/providers/dao/salt/ReflectionSaltSourceTests.java index febd64af75..ca165f08b5 100644 --- a/core/src/test/java/org/acegisecurity/providers/dao/salt/ReflectionSaltSourceTests.java +++ b/core/src/test/java/org/acegisecurity/providers/dao/salt/ReflectionSaltSourceTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* 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. @@ -67,7 +67,7 @@ public class ReflectionSaltSourceTests extends TestCase { ReflectionSaltSource saltSource = new ReflectionSaltSource(); saltSource.setUserPropertyToUse("getDoesNotExist"); - UserDetails user = new User("scott", "wombat", true, true, true, + UserDetails user = new User("scott", "wombat", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")}); try { @@ -89,7 +89,7 @@ public class ReflectionSaltSourceTests extends TestCase { saltSource.setUserPropertyToUse("getUsername"); saltSource.afterPropertiesSet(); - UserDetails user = new User("scott", "wombat", true, true, true, + UserDetails user = new User("scott", "wombat", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")}); assertEquals("scott", saltSource.getSalt(user)); } diff --git a/core/src/test/java/org/acegisecurity/providers/x509/X509AuthenticationProviderTests.java b/core/src/test/java/org/acegisecurity/providers/x509/X509AuthenticationProviderTests.java index 3aa8d37025..930cf98367 100644 --- a/core/src/test/java/org/acegisecurity/providers/x509/X509AuthenticationProviderTests.java +++ b/core/src/test/java/org/acegisecurity/providers/x509/X509AuthenticationProviderTests.java @@ -16,12 +16,14 @@ package net.sf.acegisecurity.providers.x509; import junit.framework.TestCase; + import net.sf.acegisecurity.*; -import net.sf.acegisecurity.providers.dao.User; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; +import net.sf.acegisecurity.providers.dao.User; import java.security.cert.X509Certificate; + /** * Tests {@link net.sf.acegisecurity.providers.x509.X509AuthenticationProvider} * @@ -45,17 +47,28 @@ public class X509AuthenticationProviderTests extends TestCase { super.setUp(); } - public void testRequiresPopulator() throws Exception { + public void testAuthenticationIsNullWithUnsupportedToken() { X509AuthenticationProvider provider = new X509AuthenticationProvider(); + Authentication request = new UsernamePasswordAuthenticationToken("dummy", + "dummy"); + Authentication result = provider.authenticate(request); + assertNull(result); + } + + public void testFailsWithNullCertificate() { + X509AuthenticationProvider provider = new X509AuthenticationProvider(); + + provider.setX509AuthoritiesPopulator(new MockAuthoritiesPopulator(false)); + try { - provider.afterPropertiesSet(); - fail("Should have thrown IllegalArgumentException"); - } catch (IllegalArgumentException failed) { - //ignored + provider.authenticate(new X509AuthenticationToken(null)); + fail("Should have thrown BadCredentialsException"); + } catch (BadCredentialsException e) { + //ignore } } - public void testNormalOperation () throws Exception { + public void testNormalOperation() throws Exception { X509AuthenticationProvider provider = new X509AuthenticationProvider(); provider.setX509AuthoritiesPopulator(new MockAuthoritiesPopulator(false)); @@ -67,56 +80,48 @@ public class X509AuthenticationProviderTests extends TestCase { assertNotNull(result.getAuthorities()); } - public void testFailsWithNullCertificate() { - X509AuthenticationProvider provider = new X509AuthenticationProvider(); - - provider.setX509AuthoritiesPopulator(new MockAuthoritiesPopulator(false)); - try { - provider.authenticate(new X509AuthenticationToken(null)); - fail("Should have thrown BadCredentialsException"); - } catch(BadCredentialsException e) { - //ignore - } - } - public void testPopulatorRejectionCausesFailure() throws Exception { X509AuthenticationProvider provider = new X509AuthenticationProvider(); provider.setX509AuthoritiesPopulator(new MockAuthoritiesPopulator(true)); + try { provider.authenticate(X509TestUtils.createToken()); fail("Should have thrown BadCredentialsException"); - } catch(BadCredentialsException e) { + } catch (BadCredentialsException e) { //ignore } } - public void testAuthenticationIsNullWithUnsupportedToken() { + public void testRequiresPopulator() throws Exception { X509AuthenticationProvider provider = new X509AuthenticationProvider(); - Authentication request = new UsernamePasswordAuthenticationToken("dummy","dummy"); - Authentication result = provider.authenticate(request); - assertNull(result); + + try { + provider.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException failed) { + //ignored + } } //~ Inner Classes ========================================================== - public static class MockAuthoritiesPopulator implements X509AuthoritiesPopulator { + public static class MockAuthoritiesPopulator + implements X509AuthoritiesPopulator { private boolean rejectCertificate; public MockAuthoritiesPopulator(boolean rejectCertificate) { this.rejectCertificate = rejectCertificate; } - public UserDetails getUserDetails(X509Certificate userCertificate) throws AuthenticationException { - if(rejectCertificate) { + public UserDetails getUserDetails(X509Certificate userCertificate) + throws AuthenticationException { + if (rejectCertificate) { throw new BadCredentialsException("Invalid Certificate"); } - return new User ("user", "password", true, true, true, + return new User("user", "password", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A"), new GrantedAuthorityImpl( "ROLE_B")}); } } - - - } diff --git a/core/src/test/java/org/acegisecurity/providers/x509/X509AuthenticationTokenTests.java b/core/src/test/java/org/acegisecurity/providers/x509/X509AuthenticationTokenTests.java index 94d82c1188..5f672dda4a 100644 --- a/core/src/test/java/org/acegisecurity/providers/x509/X509AuthenticationTokenTests.java +++ b/core/src/test/java/org/acegisecurity/providers/x509/X509AuthenticationTokenTests.java @@ -17,22 +17,23 @@ package net.sf.acegisecurity.providers.x509; import junit.framework.TestCase; -import java.security.cert.X509Certificate; -import java.security.cert.CertificateFactory; -import java.io.ByteArrayInputStream; /** + * DOCUMENT ME! + * * @author Luke Taylor */ public class X509AuthenticationTokenTests extends TestCase { + //~ Constructors =========================================================== - public X509AuthenticationTokenTests() { - } + public X509AuthenticationTokenTests() {} public X509AuthenticationTokenTests(String s) { super(s); } + //~ Methods ================================================================ + public void setUp() throws Exception { super.setUp(); } @@ -44,4 +45,3 @@ public class X509AuthenticationTokenTests extends TestCase { assertTrue(token.isAuthenticated()); } } - diff --git a/core/src/test/java/org/acegisecurity/providers/x509/populator/DaoX509AuthoritiesPopulatorTests.java b/core/src/test/java/org/acegisecurity/providers/x509/populator/DaoX509AuthoritiesPopulatorTests.java index db640b619d..f1058c517c 100644 --- a/core/src/test/java/org/acegisecurity/providers/x509/populator/DaoX509AuthoritiesPopulatorTests.java +++ b/core/src/test/java/org/acegisecurity/providers/x509/populator/DaoX509AuthoritiesPopulatorTests.java @@ -16,19 +16,24 @@ package net.sf.acegisecurity.providers.x509.populator; import junit.framework.TestCase; -import net.sf.acegisecurity.providers.dao.AuthenticationDao; -import net.sf.acegisecurity.providers.dao.UsernameNotFoundException; -import net.sf.acegisecurity.providers.dao.User; -import net.sf.acegisecurity.providers.x509.X509TestUtils; -import net.sf.acegisecurity.UserDetails; + +import net.sf.acegisecurity.BadCredentialsException; import net.sf.acegisecurity.GrantedAuthority; import net.sf.acegisecurity.GrantedAuthorityImpl; -import net.sf.acegisecurity.BadCredentialsException; +import net.sf.acegisecurity.UserDetails; +import net.sf.acegisecurity.providers.dao.AuthenticationDao; +import net.sf.acegisecurity.providers.dao.User; +import net.sf.acegisecurity.providers.dao.UsernameNotFoundException; +import net.sf.acegisecurity.providers.x509.X509TestUtils; + import org.springframework.dao.DataAccessException; import java.security.cert.X509Certificate; + /** + * DOCUMENT ME! + * * @author Luke Taylor */ public class DaoX509AuthoritiesPopulatorTests extends TestCase { @@ -48,29 +53,7 @@ public class DaoX509AuthoritiesPopulatorTests extends TestCase { super.setUp(); } - public void testRequiresDao() throws Exception { - DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator(); - try { - populator.afterPropertiesSet(); - fail("Should have thrown IllegalArgumentException"); - } catch(IllegalArgumentException failed) { - // ignored - } - } - - public void testInvalidRegexFails() throws Exception { - DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator(); - populator.setAuthenticationDao(new MockAuthenticationDaoMatchesNameOrEmail()); - populator.setSubjectDNRegex("CN=(.*?,"); // missing closing bracket on group - try { - populator.afterPropertiesSet(); - fail("Should have thrown IllegalArgumentException"); - } catch(IllegalArgumentException failed) { - // ignored - } - } - - public void testDefaultCNPatternMatch() throws Exception{ + public void testDefaultCNPatternMatch() throws Exception { X509Certificate cert = X509TestUtils.buildTestCertificate(); DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator(); @@ -79,7 +62,7 @@ public class DaoX509AuthoritiesPopulatorTests extends TestCase { populator.getUserDetails(cert); } - public void testEmailPatternMatch() throws Exception{ + public void testEmailPatternMatch() throws Exception { X509Certificate cert = X509TestUtils.buildTestCertificate(); DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator(); @@ -89,17 +72,15 @@ public class DaoX509AuthoritiesPopulatorTests extends TestCase { populator.getUserDetails(cert); } - public void testPatternWithNoGroupFails() throws Exception { - X509Certificate cert = X509TestUtils.buildTestCertificate(); + public void testInvalidRegexFails() throws Exception { DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator(); - populator.setAuthenticationDao(new MockAuthenticationDaoMatchesNameOrEmail()); - populator.setSubjectDNRegex("CN=.*?,"); - populator.afterPropertiesSet(); + populator.setSubjectDNRegex("CN=(.*?,"); // missing closing bracket on group + try { - populator.getUserDetails(cert); - fail("Should have thrown IllegalArgumentException for regexp without group"); - } catch (IllegalArgumentException e) { + populator.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException failed) { // ignored } } @@ -111,6 +92,7 @@ public class DaoX509AuthoritiesPopulatorTests extends TestCase { populator.setAuthenticationDao(new MockAuthenticationDaoMatchesNameOrEmail()); populator.setSubjectDNRegex("shoeSize=(.*?),"); populator.afterPropertiesSet(); + try { populator.getUserDetails(cert); fail("Should have thrown BadCredentialsException."); @@ -119,13 +101,43 @@ public class DaoX509AuthoritiesPopulatorTests extends TestCase { } } - //~ Inner Classes ========================================================== - private class MockAuthenticationDaoMatchesNameOrEmail implements AuthenticationDao { + public void testPatternWithNoGroupFails() throws Exception { + X509Certificate cert = X509TestUtils.buildTestCertificate(); + DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator(); + populator.setAuthenticationDao(new MockAuthenticationDaoMatchesNameOrEmail()); + populator.setSubjectDNRegex("CN=.*?,"); + populator.afterPropertiesSet(); + + try { + populator.getUserDetails(cert); + fail( + "Should have thrown IllegalArgumentException for regexp without group"); + } catch (IllegalArgumentException e) { + // ignored + } + } + + public void testRequiresDao() throws Exception { + DaoX509AuthoritiesPopulator populator = new DaoX509AuthoritiesPopulator(); + + try { + populator.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException failed) { + // ignored + } + } + + //~ Inner Classes ========================================================== + + private class MockAuthenticationDaoMatchesNameOrEmail + implements AuthenticationDao { public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { - if ("Luke Taylor".equals(username) || "luke@monkeymachine".equals(username)) { - return new User("luke", "monkey", true, true, true, + if ("Luke Taylor".equals(username) + || "luke@monkeymachine".equals(username)) { + return new User("luke", "monkey", true, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE")}); } else { throw new UsernameNotFoundException("Could not find: " diff --git a/core/src/test/java/org/acegisecurity/taglibs/authz/AuthenticationTagTests.java b/core/src/test/java/org/acegisecurity/taglibs/authz/AuthenticationTagTests.java index 86b3317fd8..649599c554 100644 --- a/core/src/test/java/org/acegisecurity/taglibs/authz/AuthenticationTagTests.java +++ b/core/src/test/java/org/acegisecurity/taglibs/authz/AuthenticationTagTests.java @@ -77,7 +77,7 @@ public class AuthenticationTagTests extends TestCase { public void testOperationWhenPrincipalIsAUserDetailsInstance() throws JspException { Authentication auth = new TestingAuthenticationToken(new User( - "marissaUserDetails", "koala", true, true, true, + "marissaUserDetails", "koala", true, true, true, true, new GrantedAuthority[] {}), "koala", new GrantedAuthority[] {}); SecureContext sc = new SecureContextImpl(); diff --git a/core/src/test/java/org/acegisecurity/ui/rememberme/TokenBasedRememberMeServicesTests.java b/core/src/test/java/org/acegisecurity/ui/rememberme/TokenBasedRememberMeServicesTests.java index d9c00be589..de98c059f5 100644 --- a/core/src/test/java/org/acegisecurity/ui/rememberme/TokenBasedRememberMeServicesTests.java +++ b/core/src/test/java/org/acegisecurity/ui/rememberme/TokenBasedRememberMeServicesTests.java @@ -104,6 +104,7 @@ public class TokenBasedRememberMeServicesTests extends TestCase { public void testAutoLoginIfExpired() throws Exception { UserDetails user = new User("someone", "password", true, true, true, + true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}); TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); @@ -130,6 +131,7 @@ public class TokenBasedRememberMeServicesTests extends TestCase { public void testAutoLoginIfMissingThreeTokensInCookieValue() throws Exception { UserDetails user = new User("someone", "password", true, true, true, + true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}); TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); @@ -154,6 +156,7 @@ public class TokenBasedRememberMeServicesTests extends TestCase { public void testAutoLoginIfNotBase64Encoded() throws Exception { UserDetails user = new User("someone", "password", true, true, true, + true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}); TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); @@ -179,6 +182,7 @@ public class TokenBasedRememberMeServicesTests extends TestCase { public void testAutoLoginIfSignatureBlocksDoesNotMatchExpectedValue() throws Exception { UserDetails user = new User("someone", "password", true, true, true, + true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}); TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); @@ -205,6 +209,7 @@ public class TokenBasedRememberMeServicesTests extends TestCase { public void testAutoLoginIfTokenDoesNotContainANumberInCookieValue() throws Exception { UserDetails user = new User("someone", "password", true, true, true, + true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}); TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); @@ -252,6 +257,7 @@ public class TokenBasedRememberMeServicesTests extends TestCase { public void testAutoLoginWithValidToken() throws Exception { UserDetails user = new User("someone", "password", true, true, true, + true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}); TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(); @@ -346,6 +352,7 @@ public class TokenBasedRememberMeServicesTests extends TestCase { MockHttpServletResponse response = new MockHttpServletResponse(); UserDetails user = new User("someone", "password", true, true, true, + true, new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ABC")}); services.loginSuccess(request, response, new TestingAuthenticationToken(user, "ignored", diff --git a/core/src/test/java/org/acegisecurity/wrapper/ContextHolderAwareRequestWrapperTests.java b/core/src/test/java/org/acegisecurity/wrapper/ContextHolderAwareRequestWrapperTests.java index eceedea0ea..feff0fc2c3 100644 --- a/core/src/test/java/org/acegisecurity/wrapper/ContextHolderAwareRequestWrapperTests.java +++ b/core/src/test/java/org/acegisecurity/wrapper/ContextHolderAwareRequestWrapperTests.java @@ -80,7 +80,7 @@ public class ContextHolderAwareRequestWrapperTests extends TestCase { throws Exception { SecureContext sc = new SecureContextImpl(); Authentication auth = new TestingAuthenticationToken(new User( - "marissaAsUserDetails", "koala", true, true, true, + "marissaAsUserDetails", "koala", true, true, true, true, new GrantedAuthority[] {}), "koala", new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_HELLO"), new GrantedAuthorityImpl( "ROLE_FOOBAR")}); diff --git a/doc/xdocs/changes.xml b/doc/xdocs/changes.xml index a9226b380d..329272cc68 100644 --- a/doc/xdocs/changes.xml +++ b/doc/xdocs/changes.xml @@ -26,12 +26,13 @@ - X509 (certificate-based) authentication support + X509 (certificate-based) authentication support + UserDetails now advises locked accounts, with corresponding DaoAuthenticationProvider events and enforcement ContextHolderAwareRequestWrapper methods returns null if user is anonymous AbstractBasicAclEntry improved compatibility with Hibernate SecurityEnforcementFilter caused NullPointerException when anonymous authentication used with BasicProcessingFilterEntryPoint FilterChainProxy now supports replacement of ServletRequest and ServetResponse by Filter beans - Corrected Authz parsing of whitespace in GrantedAuthoritys + Corrected Authz parsing of whitespace in GrantedAuthoritys TokenBasedRememberMeServices now respects expired users, expired credentials and disabled users HttpSessionContextIntegrationFilter now handles HttpSession invalidation without redirection diff --git a/sandbox/src/main/java/org/acegisecurity/providers/dao/ldap/LdapPasswordAuthenticationDao.java b/sandbox/src/main/java/org/acegisecurity/providers/dao/ldap/LdapPasswordAuthenticationDao.java index a2dee1b30f..742b726c99 100644 --- a/sandbox/src/main/java/org/acegisecurity/providers/dao/ldap/LdapPasswordAuthenticationDao.java +++ b/sandbox/src/main/java/org/acegisecurity/providers/dao/ldap/LdapPasswordAuthenticationDao.java @@ -721,7 +721,7 @@ public class LdapPasswordAuthenticationDao implements PasswordAuthenticationDao String[] ldapRoles = (String[]) roles.toArray(new String[] {}); - return new User(username, password, true, true, true, + return new User(username, password, true, true, true, true, getGrantedAuthorities(ldapRoles)); } catch (AuthenticationException ex) { throw new BadCredentialsException(