diff --git a/security/src/main/java/org/springframework/ws/soap/security/support/AcegiUtils.java b/security/src/main/java/org/springframework/ws/soap/security/support/AcegiUtils.java
new file mode 100644
index 00000000..5f57979f
--- /dev/null
+++ b/security/src/main/java/org/springframework/ws/soap/security/support/AcegiUtils.java
@@ -0,0 +1,58 @@
+/* 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.springframework.ws.soap.security.support;
+
+import org.acegisecurity.userdetails.UserDetails;
+import org.acegisecurity.LockedException;
+import org.acegisecurity.DisabledException;
+import org.acegisecurity.AccountExpiredException;
+import org.acegisecurity.CredentialsExpiredException;
+
+/**
+ * Generic utility methods for Spring Security
+ *
+ * @author Tareq Abedrabbo
+ * @since 1.5.8
+ */
+public abstract class AcegiUtils {
+
+ /**
+ * Checks the validity of a user's account and credentials.
+ * @param user the user to check
+ * @throws org.springframework.security.AccountExpiredException if the account has expired
+ * @throws org.springframework.security.CredentialsExpiredException if the credentials have expired
+ * @throws org.springframework.security.DisabledException if the account is disabled
+ * @throws org.springframework.security.LockedException if the account is locked
+ */
+ public static void checkUserValidity(UserDetails user)
+ throws AccountExpiredException, CredentialsExpiredException, DisabledException, LockedException {
+ if (!user.isAccountNonLocked()) {
+ throw new LockedException("User account is locked");
+ }
+
+ if (!user.isEnabled()) {
+ throw new DisabledException("User is disabled");
+ }
+
+ if (!user.isAccountNonExpired()) {
+ throw new AccountExpiredException("User account has expired");
+ }
+
+ if (!user.isCredentialsNonExpired()) {
+ throw new CredentialsExpiredException("User credentials have expired");
+ }
+ }
+}
\ No newline at end of file
diff --git a/security/src/main/java/org/springframework/ws/soap/security/support/SpringSecurityUtils.java b/security/src/main/java/org/springframework/ws/soap/security/support/SpringSecurityUtils.java
new file mode 100644
index 00000000..2501d60d
--- /dev/null
+++ b/security/src/main/java/org/springframework/ws/soap/security/support/SpringSecurityUtils.java
@@ -0,0 +1,58 @@
+/* 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.springframework.ws.soap.security.support;
+
+import org.springframework.security.userdetails.UserDetails;
+import org.springframework.security.LockedException;
+import org.springframework.security.DisabledException;
+import org.springframework.security.AccountExpiredException;
+import org.springframework.security.CredentialsExpiredException;
+
+/**
+ * Generic utility methods for Spring Security
+ *
+ * @author Tareq Abedrabbo
+ * @since 1.5.8
+ */
+public abstract class SpringSecurityUtils {
+
+ /**
+ * Checks the validity of a user's account and credentials.
+ * @param user the user to check
+ * @throws AccountExpiredException if the account has expired
+ * @throws CredentialsExpiredException if the credentials have expired
+ * @throws DisabledException if the account is disabled
+ * @throws LockedException if the account is locked
+ */
+ public static void checkUserValidity(UserDetails user)
+ throws AccountExpiredException, CredentialsExpiredException, DisabledException, LockedException {
+ if (!user.isAccountNonLocked()) {
+ throw new LockedException("User account is locked", user);
+ }
+
+ if (!user.isEnabled()) {
+ throw new DisabledException("User is disabled", user);
+ }
+
+ if (!user.isAccountNonExpired()) {
+ throw new AccountExpiredException("User account has expired", user);
+ }
+
+ if (!user.isCredentialsNonExpired()) {
+ throw new CredentialsExpiredException("User credentials have expired", user);
+ }
+ }
+}
diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringDigestPasswordValidationCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringDigestPasswordValidationCallbackHandler.java
index 586a20cd..8f2b0fe3 100644
--- a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringDigestPasswordValidationCallbackHandler.java
+++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringDigestPasswordValidationCallbackHandler.java
@@ -33,6 +33,7 @@ import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;
import org.springframework.ws.soap.security.callback.CleanupCallback;
+import org.springframework.ws.soap.security.support.SpringSecurityUtils;
/**
* Callback handler that validates a password digest using an Spring Security UserDetailsService. Logic
@@ -71,6 +72,7 @@ public class SpringDigestPasswordValidationCallbackHandler extends AbstractWsPas
String identifier = callback.getIdentifier();
UserDetails user = loadUserDetails(identifier);
if (user != null) {
+ SpringSecurityUtils.checkUserValidity(user);
callback.setPassword(user.getPassword());
}
}
diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/acegi/AcegiDigestPasswordValidationCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/acegi/AcegiDigestPasswordValidationCallbackHandler.java
index 02c8655c..edbc95f7 100644
--- a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/acegi/AcegiDigestPasswordValidationCallbackHandler.java
+++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/acegi/AcegiDigestPasswordValidationCallbackHandler.java
@@ -35,6 +35,7 @@ import org.springframework.util.Assert;
import org.springframework.ws.soap.security.callback.CleanupCallback;
import org.springframework.ws.soap.security.wss4j.callback.AbstractWsPasswordCallbackHandler;
import org.springframework.ws.soap.security.wss4j.callback.UsernameTokenPrincipalCallback;
+import org.springframework.ws.soap.security.support.AcegiUtils;
/**
* Callback handler that validates a password digest using an Acegi UserDetailsService. Logic based on
@@ -73,6 +74,7 @@ public class AcegiDigestPasswordValidationCallbackHandler extends AbstractWsPass
String identifier = callback.getIdentifier();
UserDetails user = loadUserDetails(identifier);
if (user != null) {
+ AcegiUtils.checkUserValidity(user);
callback.setPassword(user.getPassword());
}
}
diff --git a/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/SpringDigestPasswordValidationCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/SpringDigestPasswordValidationCallbackHandler.java
index 3f6af7d4..702cd77b 100644
--- a/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/SpringDigestPasswordValidationCallbackHandler.java
+++ b/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/SpringDigestPasswordValidationCallbackHandler.java
@@ -35,6 +35,7 @@ import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;
import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;
import org.springframework.ws.soap.security.callback.CleanupCallback;
+import org.springframework.ws.soap.security.support.SpringSecurityUtils;
/**
* Callback handler that validates a password digest using an Spring Security UserDetailsService. Logic
@@ -89,6 +90,7 @@ public class SpringDigestPasswordValidationCallbackHandler extends AbstractCallb
String username = request.getUsername();
UserDetails user = loadUserDetails(username);
if (user != null) {
+ SpringSecurityUtils.checkUserValidity(user);
request.setPassword(user.getPassword());
}
SpringSecurityDigestPasswordValidator validator = new SpringSecurityDigestPasswordValidator(user);
diff --git a/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/acegi/AcegiDigestPasswordValidationCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/acegi/AcegiDigestPasswordValidationCallbackHandler.java
index 3a41b7f2..8874618b 100644
--- a/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/acegi/AcegiDigestPasswordValidationCallbackHandler.java
+++ b/security/src/main/java/org/springframework/ws/soap/security/xwss/callback/acegi/AcegiDigestPasswordValidationCallbackHandler.java
@@ -36,6 +36,7 @@ import org.springframework.util.Assert;
import org.springframework.ws.soap.security.callback.AbstractCallbackHandler;
import org.springframework.ws.soap.security.callback.CleanupCallback;
import org.springframework.ws.soap.security.xwss.callback.DefaultTimestampValidator;
+import org.springframework.ws.soap.security.support.AcegiUtils;
/**
* Callback handler that validates a password digest using an Acegi UserDetailsService. Logic based on
@@ -89,6 +90,7 @@ public class AcegiDigestPasswordValidationCallbackHandler extends AbstractCallba
String username = request.getUsername();
UserDetails user = loadUserDetails(username);
if (user != null) {
+ AcegiUtils.checkUserValidity(user);
request.setPassword(user.getPassword());
}
AcegiDigestPasswordValidator validator = new AcegiDigestPasswordValidator(user);
diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/acegi/AcegiDigestPasswordValidationCallbackHandlerTest.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/acegi/AcegiDigestPasswordValidationCallbackHandlerTest.java
index 8b37a6fa..44506518 100644
--- a/security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/acegi/AcegiDigestPasswordValidationCallbackHandlerTest.java
+++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/acegi/AcegiDigestPasswordValidationCallbackHandlerTest.java
@@ -20,12 +20,14 @@ import junit.framework.TestCase;
import org.acegisecurity.Authentication;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
+import org.acegisecurity.DisabledException;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.userdetails.User;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UserDetailsService;
import org.apache.ws.security.WSUsernameTokenPrincipal;
+import org.apache.ws.security.WSPasswordCallback;
import org.easymock.MockControl;
import org.springframework.ws.soap.security.wss4j.callback.UsernameTokenPrincipalCallback;
@@ -41,31 +43,29 @@ public class AcegiDigestPasswordValidationCallbackHandlerTest extends TestCase {
private MockControl control;
- private WSUsernameTokenPrincipal principal;
-
- private UsernameTokenPrincipalCallback callback;
-
private UserDetails user;
protected void setUp() throws Exception {
callbackHandler = new AcegiDigestPasswordValidationCallbackHandler();
grantedAuthority = new GrantedAuthorityImpl("ROLE_1");
- user = new User("Ernie", "Bert", true, true, true, true, new GrantedAuthority[]{grantedAuthority});
control = MockControl.createControl(UserDetailsService.class);
userDetailsService = (UserDetailsService) control.getMock();
userDetailsService.loadUserByUsername("Ernie");
- control.setDefaultReturnValue(user);
- control.replay();
callbackHandler.setUserDetailsService(userDetailsService);
+ }
- principal = new WSUsernameTokenPrincipal("Ernie", true);
- callback = new UsernameTokenPrincipalCallback(principal);
-
+ protected void tearDown() throws Exception {
+ control.reset();
}
public void testHandleUsernameTokenPrincipal() throws Exception {
+ user = new User("Ernie", "Bert", true, true, true, true, new GrantedAuthority[]{grantedAuthority});
+ WSUsernameTokenPrincipal principal = new WSUsernameTokenPrincipal("Ernie", true);
+ UsernameTokenPrincipalCallback callback = new UsernameTokenPrincipalCallback(principal);
+ control.setDefaultReturnValue(user);
+ control.replay();
callbackHandler.handleUsernameTokenPrincipal(callback);
SecurityContext context = SecurityContextHolder.getContext();
assertNotNull("SecurityContext must not be null", context);
@@ -75,4 +75,16 @@ public class AcegiDigestPasswordValidationCallbackHandlerTest extends TestCase {
assertTrue("GrantedAuthority[] must not be null or empty", (authorities != null && authorities.length > 0));
assertEquals("Unexpected authority", grantedAuthority, authorities[0]);
}
+
+ public void testHandleUsernameTokenWithDisabledUser() throws Exception {
+ user = new User("Ernie", "Bert", false, true, true, true, new GrantedAuthority[]{grantedAuthority});
+ WSPasswordCallback callback = new WSPasswordCallback("ID", WSPasswordCallback.USERNAME_TOKEN);
+ control.setDefaultReturnValue(user);
+ control.replay();
+ try {
+ callbackHandler.handleUsernameToken(callback);
+ fail("disabled user authenticated");
+ } catch (DisabledException expected) {
+ }
+ }
}
diff --git a/security/src/test/java/org/springframework/ws/soap/security/xwss/callback/SpringDigestPasswordValidationCallbackHandlerTest.java b/security/src/test/java/org/springframework/ws/soap/security/xwss/callback/SpringDigestPasswordValidationCallbackHandlerTest.java
index 2f24cca8..d386920f 100644
--- a/security/src/test/java/org/springframework/ws/soap/security/xwss/callback/SpringDigestPasswordValidationCallbackHandlerTest.java
+++ b/security/src/test/java/org/springframework/ws/soap/security/xwss/callback/SpringDigestPasswordValidationCallbackHandlerTest.java
@@ -21,6 +21,7 @@ import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.security.GrantedAuthority;
+import org.springframework.security.DisabledException;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.TestingAuthenticationToken;
import org.springframework.security.userdetails.User;
@@ -93,6 +94,18 @@ public class SpringDigestPasswordValidationCallbackHandlerTest extends TestCase
control.verify();
}
+ public void testAuthenticateUserDigestDisbaled() throws Exception {
+ User user = new User(username, "Ernie", false, true, true, true, new GrantedAuthority[0]);
+ control.expectAndReturn(mock.loadUserByUsername(username), user);
+ control.replay();
+ try {
+ callbackHandler.handleInternal(callback);
+ fail("disabled user authenticated");
+ } catch (
+ DisabledException expected) {
+ }
+ }
+
public void testCleanUp() throws Exception {
TestingAuthenticationToken authentication =
new TestingAuthenticationToken(new Object(), new Object(), new GrantedAuthority[0]);
diff --git a/security/src/test/java/org/springframework/ws/soap/security/xwss/callback/acegi/AcegiDigestPasswordValidationCallbackHandlerTest.java b/security/src/test/java/org/springframework/ws/soap/security/xwss/callback/acegi/AcegiDigestPasswordValidationCallbackHandlerTest.java
index 0d355e60..ac2b56db 100644
--- a/security/src/test/java/org/springframework/ws/soap/security/xwss/callback/acegi/AcegiDigestPasswordValidationCallbackHandlerTest.java
+++ b/security/src/test/java/org/springframework/ws/soap/security/xwss/callback/acegi/AcegiDigestPasswordValidationCallbackHandlerTest.java
@@ -19,6 +19,7 @@ package org.springframework.ws.soap.security.xwss.callback.acegi;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback;
import junit.framework.TestCase;
import org.acegisecurity.GrantedAuthority;
+import org.acegisecurity.DisabledException;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.providers.TestingAuthenticationToken;
import org.acegisecurity.userdetails.User;
@@ -93,6 +94,18 @@ public class AcegiDigestPasswordValidationCallbackHandlerTest extends TestCase {
control.verify();
}
+ public void testAuthenticateUserDigestDisbaled() throws Exception {
+ User user = new User(username, "Ernie", false, true, true, true, new GrantedAuthority[0]);
+ control.expectAndReturn(mock.loadUserByUsername(username), user);
+ control.replay();
+ try {
+ callbackHandler.handleInternal(callback);
+ fail("disabled user authenticated");
+ } catch (
+ DisabledException expected) {
+ }
+ }
+
public void testCleanUp() throws Exception {
TestingAuthenticationToken authentication =
new TestingAuthenticationToken(new Object(), new Object(), new GrantedAuthority[0]);