diff --git a/core/src/main/java/org/acegisecurity/providers/siteminder/SiteminderAuthenticationProvider.java b/core/src/main/java/org/acegisecurity/providers/siteminder/SiteminderAuthenticationProvider.java new file mode 100644 index 0000000000..c4f7042975 --- /dev/null +++ b/core/src/main/java/org/acegisecurity/providers/siteminder/SiteminderAuthenticationProvider.java @@ -0,0 +1,132 @@ +/* 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. + * 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 org.acegisecurity.providers.siteminder; + +import org.acegisecurity.AccountExpiredException; +import org.acegisecurity.AuthenticationException; +import org.acegisecurity.AuthenticationServiceException; +import org.acegisecurity.CredentialsExpiredException; +import org.acegisecurity.DisabledException; +import org.acegisecurity.LockedException; +import org.acegisecurity.providers.AuthenticationProvider; +import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; +import org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider; +import org.acegisecurity.userdetails.UserDetails; +import org.acegisecurity.userdetails.UserDetailsService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.dao.DataAccessException; +import org.springframework.util.Assert; + +/** + * An {@link AuthenticationProvider} implementation that retrieves user details from an {@link UserDetailsService}. + * + * @author Scott McCrory + * @version $Id: SiteminderAuthenticationProvider.java 1582 2006-07-15 15:18:51Z smccrory $ + */ +public class SiteminderAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { + + /** + * Our logging object + */ + private static final Log logger = LogFactory.getLog(SiteminderAuthenticationProvider.class); + + //~ Instance fields ================================================================================================ + + /** + * Our user details service (which does the real work of checking the user against a back-end user store). + */ + private UserDetailsService userDetailsService; + + //~ Methods ======================================================================================================== + + /** + * @see org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider#additionalAuthenticationChecks(org.acegisecurity.userdetails.UserDetails, org.acegisecurity.providers.UsernamePasswordAuthenticationToken) + */ + protected void additionalAuthenticationChecks(final UserDetails user, + final UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { + + // No need for password authentication checks - we only expect one identifying string + // from the HTTP Request header (as populated by Siteminder), but we do need to see if + // the user's account is OK to let them in. + if (!user.isEnabled()) { + throw new DisabledException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled", + "Account disabled")); + } + + if (!user.isAccountNonExpired()) { + throw new AccountExpiredException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.expired", + "Account expired")); + } + + if (!user.isAccountNonLocked()) { + throw new LockedException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked", + "Account locked")); + } + + if (!user.isCredentialsNonExpired()) { + throw new CredentialsExpiredException(messages.getMessage( + "AbstractUserDetailsAuthenticationProvider.credentialsExpired", "Credentials expired")); + } + + } + + /** + * @see org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider#doAfterPropertiesSet() + */ + protected void doAfterPropertiesSet() throws Exception { + Assert.notNull(this.userDetailsService, "A UserDetailsService must be set"); + } + + /** + * Return the user details service. + * @return The user details service. + */ + public UserDetailsService getUserDetailsService() { + return userDetailsService; + } + + /** + * @see org.acegisecurity.providers.dao.AbstractUserDetailsAuthenticationProvider#retrieveUser(java.lang.String, org.acegisecurity.providers.UsernamePasswordAuthenticationToken) + */ + protected final UserDetails retrieveUser(final String username, + final UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { + + UserDetails loadedUser; + + try { + loadedUser = this.getUserDetailsService().loadUserByUsername(username); + } catch (DataAccessException repositoryProblem) { + throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem); + } + + if (loadedUser == null) { + throw new AuthenticationServiceException( + "UserDetailsService returned null, which is an interface contract violation"); + } + + return loadedUser; + } + + /** + * Sets the user details service. + * @param userDetailsService The user details service. + */ + public void setUserDetailsService(final UserDetailsService userDetailsService) { + this.userDetailsService = userDetailsService; + } + +} diff --git a/core/src/main/java/org/acegisecurity/providers/siteminder/package.html b/core/src/main/java/org/acegisecurity/providers/siteminder/package.html new file mode 100644 index 0000000000..7457c82eed --- /dev/null +++ b/core/src/main/java/org/acegisecurity/providers/siteminder/package.html @@ -0,0 +1,5 @@ + +
+A Siteminder authentication provider. + + diff --git a/core/src/main/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessingFilter.java b/core/src/main/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessingFilter.java index 2f3ce4573f..bd95cc48d2 100644 --- a/core/src/main/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessingFilter.java +++ b/core/src/main/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessingFilter.java @@ -15,36 +15,40 @@ package org.acegisecurity.ui.webapp; -import org.acegisecurity.Authentication; -import org.acegisecurity.AuthenticationException; - -import org.acegisecurity.context.HttpSessionContextIntegrationFilter; -import org.acegisecurity.context.SecurityContext; - -import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.acegisecurity.Authentication; +import org.acegisecurity.AuthenticationException; +import org.acegisecurity.context.HttpSessionContextIntegrationFilter; +import org.acegisecurity.context.SecurityContext; +import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** - * Extends Acegi's AuthenticationProcessingFilter to pick up CA/Netegrity Siteminder headers.Also provides a - * backup form-based authentication and the ability set source key names.
- *Siteminder must present two headers to this filter, a username and password. You must set the + * Extends Acegi's AuthenticationProcessingFilter to pick up CA/Netegrity Siteminder headers. + * + *
Also provides a backup form-based authentication and the ability set source key names.
+ * + *Siteminder must present two headers to this filter, a username and password. You must set the * header keys before this filter is used for authentication, otherwise Siteminder checks will be skipped. If the * Siteminder check is unsuccessful (i.e. if the headers are not found), then the form parameters will be checked (see * next paragraph). This allows applications to optionally function even when their Siteminder infrastructure is * unavailable, as is often the case during development.
- *Login forms must present two parameters to this filter: a username and password. If not + * + *
Login forms must present two parameters to this filter: a username and password. If not * specified, the parameter names to use are contained in the static fields {@link #ACEGI_SECURITY_FORM_USERNAME_KEY} * and {@link #ACEGI_SECURITY_FORM_PASSWORD_KEY}.
- *Do not use this class directly. Instead, configure web.xml to use the {@link
+ *
+ *
Do not use this class directly. Instead, configure web.xml to use the {@link
* org.acegisecurity.util.FilterToBeanProxy}.
Authentication request token to the
- * AuthenticationManager
+ * AuthenticationManager (null).
*/
- protected String obtainPassword(HttpServletRequest request) {
- if ((formPasswordParameterKey != null) && (formPasswordParameterKey.length() > 0)) {
- return request.getParameter(formPasswordParameterKey);
- } else {
- return request.getParameter(ACEGI_SECURITY_FORM_PASSWORD_KEY);
- }
+ protected String obtainPassword(final HttpServletRequest request) {
+ return null;
}
/**
@@ -197,6 +160,7 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
* javax.servlet.http.HttpServletResponse)
*/
protected boolean requiresAuthentication(final HttpServletRequest request, final HttpServletResponse response) {
+
String uri = request.getRequestURI();
int pathParamIndex = uri.indexOf(';');
@@ -208,8 +172,8 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
//attempt authentication if j_secuity_check is present or if the getDefaultTargetUrl()
//is present and user is not already authenticated.
boolean bAuthenticated = false;
- SecurityContext context = (SecurityContext) request.getSession()
- .getAttribute(HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY);
+ SecurityContext context = (SecurityContext) request.getSession().getAttribute(
+ HttpSessionContextIntegrationFilter.ACEGI_SECURITY_CONTEXT_KEY);
if (context != null) {
Authentication auth = context.getAuthentication();
@@ -222,7 +186,7 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
// if true is returned then authentication will be attempted.
boolean bAttemptAuthentication = (uri.endsWith(request.getContextPath() + getFilterProcessesUrl()))
- || ((getDefaultTargetUrl() != null) && uri.endsWith(getDefaultTargetUrl()) && !bAuthenticated);
+ || ((getDefaultTargetUrl() != null) && uri.endsWith(getDefaultTargetUrl()) && !bAuthenticated);
if (logger.isDebugEnabled()) {
logger.debug("Authentication attempted for the following URI ==> " + uri + " is " + bAttemptAuthentication);
@@ -231,15 +195,6 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
return bAttemptAuthentication;
}
- /**
- * Sets the form password parameter key.
- *
- * @param key The form password parameter key.
- */
- public void setFormPasswordParameterKey(final String key) {
- this.formPasswordParameterKey = key;
- }
-
/**
* Sets the form username parameter key.
*
@@ -249,15 +204,6 @@ public class SiteminderAuthenticationProcessingFilter extends AuthenticationProc
this.formUsernameParameterKey = key;
}
- /**
- * Sets the Siteminder password header key.
- *
- * @param key The Siteminder password header key.
- */
- public void setSiteminderPasswordHeaderKey(final String key) {
- this.siteminderPasswordHeaderKey = key;
- }
-
/**
* Sets the Siteminder username header key.
*
diff --git a/core/src/main/java/org/acegisecurity/ui/webapp/package.html b/core/src/main/java/org/acegisecurity/ui/webapp/package.html
index 1fd2d439e8..f37f81c844 100644
--- a/core/src/main/java/org/acegisecurity/ui/webapp/package.html
+++ b/core/src/main/java/org/acegisecurity/ui/webapp/package.html
@@ -1,5 +1,5 @@
-Authenticates users via a standard web form and HttpSession.
+Authenticates users via HTTP properties, headers and session.
diff --git a/core/src/test/java/org/acegisecurity/providers/siteminder/SiteminderAuthenticationProviderTests.java b/core/src/test/java/org/acegisecurity/providers/siteminder/SiteminderAuthenticationProviderTests.java
new file mode 100644
index 0000000000..a8df07ec39
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/providers/siteminder/SiteminderAuthenticationProviderTests.java
@@ -0,0 +1,430 @@
+/* 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.
+ * 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 org.acegisecurity.providers.siteminder;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.acegisecurity.AccountExpiredException;
+import org.acegisecurity.Authentication;
+import org.acegisecurity.AuthenticationServiceException;
+import org.acegisecurity.BadCredentialsException;
+import org.acegisecurity.CredentialsExpiredException;
+import org.acegisecurity.DisabledException;
+import org.acegisecurity.GrantedAuthority;
+import org.acegisecurity.GrantedAuthorityImpl;
+import org.acegisecurity.LockedException;
+import org.acegisecurity.providers.TestingAuthenticationToken;
+import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
+import org.acegisecurity.providers.dao.UserCache;
+import org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache;
+import org.acegisecurity.providers.dao.cache.NullUserCache;
+import org.acegisecurity.userdetails.User;
+import org.acegisecurity.userdetails.UserDetails;
+import org.acegisecurity.userdetails.UserDetailsService;
+import org.acegisecurity.userdetails.UsernameNotFoundException;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DataRetrievalFailureException;
+
+/**
+ * Tests {@link SiteminderAuthenticationProvider}.
+ *
+ * @author Ben Alex
+ * @version $Id: SiteminderAuthenticationProviderTests.java 1582 2006-07-15 15:18:51Z smccrory $
+ */
+public class SiteminderAuthenticationProviderTests extends TestCase {
+ //~ Methods ========================================================================================================
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(SiteminderAuthenticationProviderTests.class);
+ }
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public void testAuthenticateFailsIfAccountExpired() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal");
+
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ provider.setUserDetailsService(new MockUserDetailsServiceUserPeterAccountExpired());
+ provider.setUserCache(new MockUserCache());
+
+ try {
+ provider.authenticate(token);
+ fail("Should have thrown AccountExpiredException");
+ } catch (AccountExpiredException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testAuthenticateFailsIfAccountLocked() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal");
+
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ provider.setUserDetailsService(new MockUserDetailsServiceUserPeterAccountLocked());
+ provider.setUserCache(new MockUserCache());
+
+ try {
+ provider.authenticate(token);
+ fail("Should have thrown LockedException");
+ } catch (LockedException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testAuthenticateFailsIfCredentialsExpired() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal");
+
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ provider.setUserDetailsService(new MockUserDetailsServiceUserPeterCredentialsExpired());
+ provider.setUserCache(new MockUserCache());
+
+ try {
+ provider.authenticate(token);
+ fail("Should have thrown CredentialsExpiredException");
+ } catch (CredentialsExpiredException expected) {
+ assertTrue(true);
+ }
+
+ }
+
+ public void testAuthenticateFailsIfUserDisabled() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter", "opal");
+
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ provider.setUserDetailsService(new MockUserDetailsServiceUserPeter());
+ provider.setUserCache(new MockUserCache());
+
+ try {
+ provider.authenticate(token);
+ fail("Should have thrown DisabledException");
+ } catch (DisabledException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testAuthenticateFailsWhenUserDetailsServiceHasBackendFailure() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala");
+
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ provider.setUserDetailsService(new MockUserDetailsServiceSimulateBackendError());
+ provider.setUserCache(new MockUserCache());
+
+ try {
+ provider.authenticate(token);
+ fail("Should have thrown AuthenticationServiceException");
+ } catch (AuthenticationServiceException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testAuthenticateFailsWithEmptyUsername() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, "koala");
+
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
+ provider.setUserCache(new MockUserCache());
+
+ try {
+ provider.authenticate(token);
+ fail("Should have thrown BadCredentialsException");
+ } catch (BadCredentialsException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionFalse() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER", "koala");
+
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ provider.setHideUserNotFoundExceptions(false); // we want UsernameNotFoundExceptions
+ provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
+ provider.setUserCache(new MockUserCache());
+
+ try {
+ provider.authenticate(token);
+ fail("Should have thrown UsernameNotFoundException");
+ } catch (UsernameNotFoundException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionsWithDefaultOfTrue() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER", "koala");
+
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ assertTrue(provider.isHideUserNotFoundExceptions());
+ provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
+ provider.setUserCache(new MockUserCache());
+
+ try {
+ provider.authenticate(token);
+ fail("Should have thrown BadCredentialsException");
+ } catch (BadCredentialsException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testAuthenticateFailsWithMixedCaseUsernameIfDefaultChanged() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("MaRiSSA", "koala");
+
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
+ provider.setUserCache(new MockUserCache());
+
+ try {
+ provider.authenticate(token);
+ fail("Should have thrown BadCredentialsException");
+ } catch (BadCredentialsException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testAuthenticates() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala");
+ token.setDetails("192.168.0.1");
+
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
+ provider.setUserCache(new MockUserCache());
+
+ Authentication result = provider.authenticate(token);
+
+ if (!(result instanceof UsernamePasswordAuthenticationToken)) {
+ fail("Should have returned instance of UsernamePasswordAuthenticationToken");
+ }
+
+ UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result;
+ assertEquals(User.class, castResult.getPrincipal().getClass());
+ assertEquals("koala", castResult.getCredentials());
+ assertEquals("ROLE_ONE", castResult.getAuthorities()[0].getAuthority());
+ assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority());
+ assertEquals("192.168.0.1", castResult.getDetails());
+ }
+
+ public void testAuthenticatesASecondTime() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala");
+
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
+ provider.setUserCache(new MockUserCache());
+
+ Authentication result = provider.authenticate(token);
+
+ if (!(result instanceof UsernamePasswordAuthenticationToken)) {
+ fail("Should have returned instance of UsernamePasswordAuthenticationToken");
+ }
+
+ // Now try to authenticate with the previous result (with its UserDetails)
+ Authentication result2 = provider.authenticate(result);
+
+ if (!(result2 instanceof UsernamePasswordAuthenticationToken)) {
+ fail("Should have returned instance of UsernamePasswordAuthenticationToken");
+ }
+
+ assertEquals(result.getCredentials(), result2.getCredentials());
+ }
+
+ public void testAuthenticatesWithForcePrincipalAsString() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala");
+
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
+ provider.setUserCache(new MockUserCache());
+ provider.setForcePrincipalAsString(true);
+
+ Authentication result = provider.authenticate(token);
+
+ if (!(result instanceof UsernamePasswordAuthenticationToken)) {
+ fail("Should have returned instance of UsernamePasswordAuthenticationToken");
+ }
+
+ UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result;
+ assertEquals(String.class, castResult.getPrincipal().getClass());
+ assertEquals("marissa", castResult.getPrincipal());
+ }
+
+ public void testDetectsNullBeingReturnedFromUserDetailsService() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa", "koala");
+
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ provider.setUserDetailsService(new MockUserDetailsServiceReturnsNull());
+
+ try {
+ provider.authenticate(token);
+ fail("Should have thrown AuthenticationServiceException");
+ } catch (AuthenticationServiceException expected) {
+ assertEquals("UserDetailsService returned null, which is an interface contract violation", expected
+ .getMessage());
+ }
+ }
+
+ public void testGettersSetters() {
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+
+ provider.setUserCache(new EhCacheBasedUserCache());
+ assertEquals(EhCacheBasedUserCache.class, provider.getUserCache().getClass());
+
+ assertFalse(provider.isForcePrincipalAsString());
+ provider.setForcePrincipalAsString(true);
+ assertTrue(provider.isForcePrincipalAsString());
+ }
+
+ public void testStartupFailsIfNoUserDetailsService() throws Exception {
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+
+ try {
+ provider.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testStartupFailsIfNoUserCacheSet() throws Exception {
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ provider.setUserDetailsService(new MockUserDetailsServiceUserMarissa());
+ assertEquals(NullUserCache.class, provider.getUserCache().getClass());
+ provider.setUserCache(null);
+
+ try {
+ provider.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testStartupSuccess() throws Exception {
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ UserDetailsService userDetailsService = new MockUserDetailsServiceUserMarissa();
+ provider.setUserDetailsService(userDetailsService);
+ provider.setUserCache(new MockUserCache());
+ assertEquals(userDetailsService, provider.getUserDetailsService());
+ provider.afterPropertiesSet();
+ assertTrue(true);
+ }
+
+ public void testSupports() {
+ SiteminderAuthenticationProvider provider = new SiteminderAuthenticationProvider();
+ assertTrue(provider.supports(UsernamePasswordAuthenticationToken.class));
+ assertTrue(!provider.supports(TestingAuthenticationToken.class));
+ }
+
+ //~ Inner Classes ==================================================================================================
+
+ private class MockUserDetailsServiceReturnsNull implements UserDetailsService {
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
+ return null;
+ }
+ }
+
+ private class MockUserDetailsServiceSimulateBackendError implements UserDetailsService {
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
+ throw new DataRetrievalFailureException("This mock simulator is designed to fail");
+ }
+ }
+
+ private class MockUserDetailsServiceUserMarissa implements UserDetailsService {
+ private String password = "koala";
+
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
+ if ("marissa".equals(username)) {
+ return new User("marissa", password, true, true, true, true, new GrantedAuthority[] {
+ new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") });
+ } else {
+ throw new UsernameNotFoundException("Could not find: " + username);
+ }
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+ }
+
+ private class MockUserDetailsServiceUserMarissaWithSalt implements UserDetailsService {
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
+ if ("marissa".equals(username)) {
+ return new User("marissa", "koala{SYSTEM_SALT_VALUE}", true, true, true, true, new GrantedAuthority[] {
+ new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") });
+ } else {
+ throw new UsernameNotFoundException("Could not find: " + username);
+ }
+ }
+ }
+
+ private class MockUserDetailsServiceUserPeter implements UserDetailsService {
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
+ if ("peter".equals(username)) {
+ return new User("peter", "opal", false, true, true, true, new GrantedAuthority[] {
+ new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") });
+ } else {
+ throw new UsernameNotFoundException("Could not find: " + username);
+ }
+ }
+ }
+
+ private class MockUserDetailsServiceUserPeterAccountExpired implements UserDetailsService {
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
+ if ("peter".equals(username)) {
+ 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 MockUserDetailsServiceUserPeterAccountLocked implements UserDetailsService {
+ 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 {
+ throw new UsernameNotFoundException("Could not find: " + username);
+ }
+ }
+ }
+
+ private class MockUserDetailsServiceUserPeterCredentialsExpired implements UserDetailsService {
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
+ if ("peter".equals(username)) {
+ return new User("peter", "opal", true, true, false, true, new GrantedAuthority[] {
+ new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO") });
+ } else {
+ throw new UsernameNotFoundException("Could not find: " + username);
+ }
+ }
+ }
+
+ private class MockUserCache implements UserCache {
+ private Map cache = new HashMap();
+
+ public UserDetails getUserFromCache(String username) {
+ return (User) cache.get(username);
+ }
+
+ public void putUserInCache(UserDetails user) {
+ cache.put(user.getUsername(), user);
+ }
+
+ public void removeUserFromCache(String username) {
+ }
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessingFilterTests.java b/core/src/test/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessingFilterTests.java
index 88db18a340..afd6c0b50a 100644
--- a/core/src/test/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessingFilterTests.java
+++ b/core/src/test/java/org/acegisecurity/ui/webapp/SiteminderAuthenticationProcessingFilterTests.java
@@ -19,13 +19,10 @@ import junit.framework.TestCase;
import org.acegisecurity.Authentication;
import org.acegisecurity.MockAuthenticationManager;
-
import org.acegisecurity.ui.WebAuthenticationDetails;
-
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
-
/**
* Tests SiteminderAuthenticationProcessingFilter.
*
@@ -36,18 +33,18 @@ import org.springframework.mock.web.MockHttpServletResponse;
public class SiteminderAuthenticationProcessingFilterTests extends TestCase {
//~ Constructors ===================================================================================================
-/**
- * Basic constructor.
- */
+ /**
+ * Basic constructor.
+ */
public SiteminderAuthenticationProcessingFilterTests() {
super();
}
-/**
- * Argument constructor.
- *
- * @param arg0
- */
+ /**
+ * Argument constructor.
+ *
+ * @param arg0
+ */
public SiteminderAuthenticationProcessingFilterTests(String arg0) {
super(arg0);
}
@@ -92,15 +89,9 @@ public class SiteminderAuthenticationProcessingFilterTests extends TestCase {
filter.setFilterProcessesUrl("foobar");
assertEquals("foobar", filter.getFilterProcessesUrl());
- filter.setFormPasswordParameterKey("passwordParamKey");
- assertEquals("passwordParamKey", filter.getFormPasswordParameterKey());
-
filter.setFormUsernameParameterKey("usernameParamKey");
assertEquals("usernameParamKey", filter.getFormUsernameParameterKey());
- filter.setSiteminderPasswordHeaderKey("passwordHeaderKey");
- assertEquals("passwordHeaderKey", filter.getSiteminderPasswordHeaderKey());
-
filter.setSiteminderUsernameHeaderKey("usernameHeaderKey");
assertEquals("usernameHeaderKey", filter.getSiteminderUsernameHeaderKey());
}
@@ -131,8 +122,7 @@ public class SiteminderAuthenticationProcessingFilterTests extends TestCase {
*
* @throws Exception
*/
- public void testFormNullPasswordHandledGracefully()
- throws Exception {
+ public void testFormNullPasswordHandledGracefully() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.addParameter(SiteminderAuthenticationProcessingFilter.ACEGI_SECURITY_FORM_USERNAME_KEY, "marissa");
@@ -151,8 +141,7 @@ public class SiteminderAuthenticationProcessingFilterTests extends TestCase {
*
* @throws Exception
*/
- public void testFormNullUsernameHandledGracefully()
- throws Exception {
+ public void testFormNullUsernameHandledGracefully() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.addParameter(SiteminderAuthenticationProcessingFilter.ACEGI_SECURITY_FORM_PASSWORD_KEY, "koala");
@@ -186,7 +175,6 @@ public class SiteminderAuthenticationProcessingFilterTests extends TestCase {
filter.setAuthenticationManager(authMgrThatGrantsAccess);
filter.setSiteminderUsernameHeaderKey("SM_USER");
- filter.setSiteminderPasswordHeaderKey("SM_USER");
filter.init(null);
// Requests for an unknown URL should NOT require (re)authentication
@@ -220,7 +208,6 @@ public class SiteminderAuthenticationProcessingFilterTests extends TestCase {
SiteminderAuthenticationProcessingFilter filter = new SiteminderAuthenticationProcessingFilter();
filter.setAuthenticationManager(authMgr);
filter.setSiteminderUsernameHeaderKey("SM_USER");
- filter.setSiteminderPasswordHeaderKey("SM_USER");
filter.init(null);
Authentication result = filter.attemptAuthentication(request);
diff --git a/doc/docbook/acegi.xml b/doc/docbook/acegi.xml
index f46608ff85..3049961963 100644
--- a/doc/docbook/acegi.xml
+++ b/doc/docbook/acegi.xml
@@ -2120,7 +2120,8 @@ if (obj instanceof UserDetails) {
Associates.