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 288ce23910..a863be2387 100644
--- a/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java
+++ b/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java
@@ -22,6 +22,7 @@ import net.sf.acegisecurity.BadCredentialsException;
import net.sf.acegisecurity.DisabledException;
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.AuthenticationFailureDisabledEvent;
import net.sf.acegisecurity.providers.dao.event.AuthenticationFailurePasswordEvent;
import net.sf.acegisecurity.providers.dao.event.AuthenticationSuccessEvent;
@@ -36,32 +37,26 @@ import org.springframework.context.ApplicationContextAware;
import org.springframework.dao.DataAccessException;
-import java.util.Date;
-
/**
* An {@link AuthenticationProvider} implementation that retrieves user details
* from an {@link AuthenticationDao}.
*
*
- * This AuthenticationProvider is capable of validating {@link
+ * This AuthenticationProvider is capable of validating {@link
* UsernamePasswordAuthenticationToken} requests contain the correct username,
* password and the user is not disabled.
*
*
*
- * Upon successful validation, a DaoAuthenticationToken will be
- * created and returned to the caller. This token will be signed with the key
- * configured by {@link #getKey()} and expire {@link
- * #getRefreshTokenInterval()} milliseconds into the future. The token will be
- * assumed to remain valid whilstever it has not expired, and no requests of
- * the AuthenticationProvider will need to be made. Once the
- * token has expired, the relevant AuthenticationProvider will be
- * called again to provide an updated enabled/disabled status, and list of
- * granted authorities. It should be noted the credentials will not be
- * revalidated, as the user presented correct credentials in the originial
- * UsernamePasswordAuthenticationToken. This avoids complications
- * if the user changes their password during the session.
+ * Upon successful validation, a
+ * UsernamePasswordAuthenticationToken will be created and
+ * returned to the caller. In addition, the {@link User} will be placed in the
+ * {@link UserCache} so that subsequent requests with the same username can be
+ * validated without needing to query the {@link AuthenticationDao}. It should
+ * be noted that if a user appears to present an incorrect password, the
+ * {@link AuthenticationDao} will be queried to confirm the most up-to-date
+ * password was used for comparison.
*
*
*
@@ -83,8 +78,7 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
private AuthenticationDao authenticationDao;
private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();
private SaltSource saltSource;
- private String key;
- private long refreshTokenInterval = 60000; // 60 seconds
+ private UserCache userCache = new NullUserCache();
//~ Methods ================================================================
@@ -101,14 +95,6 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
return authenticationDao;
}
- public void setKey(String key) {
- this.key = key;
- }
-
- public String getKey() {
- return key;
- }
-
/**
* Sets the PasswordEncoder instance to be used to encode and validate
* passwords. If not set, {@link PlaintextPasswordEncoder} will be used by
@@ -124,22 +110,6 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
return passwordEncoder;
}
- public void setRefreshTokenInterval(long refreshTokenInterval) {
- this.refreshTokenInterval = refreshTokenInterval;
- }
-
- /**
- * Indicates the number of seconds a created
- * DaoAuthenticationToken will remain valid for. Whilstever
- * the token is valid, the DaoAuthenticationProvider will
- * only check it presents the expected key hash code.
- *
- * @return Returns the refreshTokenInterval.
- */
- public long getRefreshTokenInterval() {
- return refreshTokenInterval;
- }
-
/**
* The source of salts to use when decoding passwords. null
* is a valid value, meaning the DaoAuthenticationProvider
@@ -157,46 +127,36 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
return saltSource;
}
+ public void setUserCache(UserCache userCache) {
+ this.userCache = userCache;
+ }
+
+ public UserCache getUserCache() {
+ return userCache;
+ }
+
public void afterPropertiesSet() throws Exception {
if (this.authenticationDao == null) {
throw new IllegalArgumentException(
"An Authentication DAO must be set");
}
- if ((this.key == null) || "".equals(key)) {
- throw new IllegalArgumentException("A key must be set");
+ if (this.userCache == null) {
+ throw new IllegalArgumentException("A user cache must be set");
}
}
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
- // If an existing DaoAuthenticationToken, check we created it and it hasn't expired
- if (authentication instanceof DaoAuthenticationToken) {
- if (this.key.hashCode() == ((DaoAuthenticationToken) authentication)
- .getKeyHash()) {
- if (((DaoAuthenticationToken) authentication).getExpires()
- .after(new Date())) {
- return authentication;
- }
- } else {
- throw new BadCredentialsException(
- "The presented DaoAuthenticationToken does not contain the expected key");
- }
+ boolean cacheWasUsed = true;
+ User user = this.userCache.getUserFromCache(authentication.getPrincipal()
+ .toString());
+
+ if (user == null) {
+ cacheWasUsed = false;
+ user = getUserFromBackend(authentication);
}
- // We need to authenticate or refresh the token
- User user = null;
-
- try {
- user = this.authenticationDao.loadUserByUsername(authentication.getPrincipal()
- .toString());
- } catch (UsernameNotFoundException notFound) {
- throw new BadCredentialsException("Bad credentials presented");
- } catch (DataAccessException repositoryProblem) {
- throw new AuthenticationServiceException(repositoryProblem
- .getMessage(), repositoryProblem);
- }
-
if (!user.isEnabled()) {
if (this.ctx != null) {
ctx.publishEvent(new AuthenticationFailureDisabledEvent(
@@ -206,16 +166,14 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
throw new DisabledException("User is disabled");
}
- if (!(authentication instanceof DaoAuthenticationToken)) {
- // Must validate credentials, as this is not simply a token refresh
- Object salt = null;
-
- if (this.saltSource != null) {
- salt = this.saltSource.getSalt(user);
+ if (!isPasswordCorrect(authentication, user)) {
+ // Password incorrect, so ensure we're using most current password
+ if (cacheWasUsed) {
+ cacheWasUsed = false;
+ user = getUserFromBackend(authentication);
}
- if (!passwordEncoder.isPasswordValid(user.getPassword(),
- authentication.getCredentials().toString(), salt)) {
+ if (!isPasswordCorrect(authentication, user)) {
if (this.ctx != null) {
ctx.publishEvent(new AuthenticationFailurePasswordEvent(
authentication, user));
@@ -225,24 +183,50 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
}
}
- Date expiry = new Date(new Date().getTime()
- + this.getRefreshTokenInterval());
+ if (!cacheWasUsed) {
+ // Put into cache
+ this.userCache.putUserInCache(user);
- if (this.ctx != null) {
- ctx.publishEvent(new AuthenticationSuccessEvent(authentication, user));
+ // As this appears to be an initial login, publish the event
+ if (this.ctx != null) {
+ ctx.publishEvent(new AuthenticationSuccessEvent(
+ authentication, user));
+ }
}
- return new DaoAuthenticationToken(this.getKey(), expiry,
- user.getUsername(), user.getPassword(), user.getAuthorities());
+ return new UsernamePasswordAuthenticationToken(user.getUsername(),
+ user.getPassword(), user.getAuthorities());
}
public boolean supports(Class authentication) {
if (UsernamePasswordAuthenticationToken.class.isAssignableFrom(
- authentication)
- || (DaoAuthenticationToken.class.isAssignableFrom(authentication))) {
+ authentication)) {
return true;
} else {
return false;
}
}
+
+ private boolean isPasswordCorrect(Authentication authentication, User user) {
+ Object salt = null;
+
+ if (this.saltSource != null) {
+ salt = this.saltSource.getSalt(user);
+ }
+
+ return passwordEncoder.isPasswordValid(user.getPassword(),
+ authentication.getCredentials().toString(), salt);
+ }
+
+ private User getUserFromBackend(Authentication authentication) {
+ try {
+ return this.authenticationDao.loadUserByUsername(authentication.getPrincipal()
+ .toString());
+ } catch (UsernameNotFoundException notFound) {
+ throw new BadCredentialsException("Bad credentials presented");
+ } catch (DataAccessException repositoryProblem) {
+ throw new AuthenticationServiceException(repositoryProblem
+ .getMessage(), repositoryProblem);
+ }
+ }
}
diff --git a/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationToken.java b/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationToken.java
deleted file mode 100644
index b9cbc4ec54..0000000000
--- a/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationToken.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/* Copyright 2004 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;
-
-import net.sf.acegisecurity.GrantedAuthority;
-import net.sf.acegisecurity.providers.AbstractAuthenticationToken;
-
-import java.io.Serializable;
-
-import java.util.Date;
-
-
-/**
- * Represents a successful DAO-based Authentication.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class DaoAuthenticationToken extends AbstractAuthenticationToken
- implements Serializable {
- //~ Instance fields ========================================================
-
- private Date expires;
- private Object credentials;
- private Object principal;
- private GrantedAuthority[] authorities;
- private int keyHash;
-
- //~ Constructors ===========================================================
-
- /**
- * Constructor.
- *
- * @param key to identify if this object made by a given {@link
- * DaoAuthenticationProvider}
- * @param expires when the token is due to expire
- * @param principal the username from the {@link User} object
- * @param credentials the password from the {@link User} object
- * @param authorities the authorities granted to the user, from the {@link
- * User} object
- *
- * @throws IllegalArgumentException if a null was passed
- */
- public DaoAuthenticationToken(String key, Date expires, Object principal,
- Object credentials, GrantedAuthority[] authorities) {
- if ((key == null) || ("".equals(key)) || (expires == null)
- || (principal == null) || "".equals(principal)
- || (credentials == null) || "".equals(credentials)
- || (authorities == null)) {
- throw new IllegalArgumentException(
- "Cannot pass null or empty values to constructor");
- }
-
- for (int i = 0; i < authorities.length; i++) {
- if (authorities[i] == null) {
- throw new IllegalArgumentException("Granted authority element "
- + i
- + " is null - GrantedAuthority[] cannot contain any null elements");
- }
- }
-
- this.keyHash = key.hashCode();
- this.expires = expires;
- this.principal = principal;
- this.credentials = credentials;
- this.authorities = authorities;
- }
-
- protected DaoAuthenticationToken() {
- throw new IllegalArgumentException("Cannot use default constructor");
- }
-
- //~ Methods ================================================================
-
- /**
- * Ignored (always true).
- *
- * @param isAuthenticated ignored
- */
- public void setAuthenticated(boolean isAuthenticated) {
- // ignored
- }
-
- /**
- * Always returns true.
- *
- * @return true
- */
- public boolean isAuthenticated() {
- return true;
- }
-
- public GrantedAuthority[] getAuthorities() {
- return this.authorities;
- }
-
- public Object getCredentials() {
- return this.credentials;
- }
-
- public Date getExpires() {
- return this.expires;
- }
-
- public int getKeyHash() {
- return this.keyHash;
- }
-
- public Object getPrincipal() {
- return this.principal;
- }
-
- public boolean equals(Object obj) {
- if (!super.equals(obj)) {
- return false;
- }
-
- if (obj instanceof DaoAuthenticationToken) {
- DaoAuthenticationToken test = (DaoAuthenticationToken) obj;
-
- if (this.getKeyHash() != test.getKeyHash()) {
- return false;
- }
-
- // expires never null due to constructor
- if (this.getExpires() != test.getExpires()) {
- return false;
- }
-
- return true;
- }
-
- return false;
- }
-
- public String toString() {
- StringBuffer sb = new StringBuffer();
- sb.append(super.toString());
- sb.append("; Expires: " + this.expires.toString());
-
- return sb.toString();
- }
-}
diff --git a/core/src/main/java/org/acegisecurity/providers/dao/UserCache.java b/core/src/main/java/org/acegisecurity/providers/dao/UserCache.java
new file mode 100644
index 0000000000..9daa3fc2c8
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/providers/dao/UserCache.java
@@ -0,0 +1,53 @@
+/* Copyright 2004 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;
+
+/**
+ * Provides a cache of {@link User} objects.
+ *
+ *
+ * Implementations should provide appropriate methods to set their cache
+ * parameters (eg time-to-live) and/or force removal of entities before their
+ * normal expiration. These are not part of the UserCache
+ * interface contract because they vary depending on the type of caching
+ * system used (eg in-memory vs disk vs cluster vs hybrid).
+ *
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public interface UserCache {
+ //~ Methods ================================================================
+
+ /**
+ * Obtains a {@link User} from the cache.
+ *
+ * @param username the {@link User#getUsername()} used to place the user in
+ * the cache
+ *
+ * @return the populated User or null if the user
+ * could not be found or if the cache entry has expired
+ */
+ public User getUserFromCache(String username);
+
+ /**
+ * Places a {@link User} in the cache. The username is the key
+ * used to subsequently retrieve the User.
+ *
+ * @param user the fully populated User to place in the cache
+ */
+ public void putUserInCache(User user);
+}
diff --git a/core/src/main/java/org/acegisecurity/providers/dao/cache/EhCacheBasedUserCache.java b/core/src/main/java/org/acegisecurity/providers/dao/cache/EhCacheBasedUserCache.java
new file mode 100644
index 0000000000..7f248667ed
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/providers/dao/cache/EhCacheBasedUserCache.java
@@ -0,0 +1,135 @@
+/* Copyright 2004 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.cache;
+
+import net.sf.acegisecurity.providers.dao.User;
+import net.sf.acegisecurity.providers.dao.UserCache;
+
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheException;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Element;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+
+import org.springframework.dao.DataRetrievalFailureException;
+
+
+/**
+ * Caches User objects using EHCACHE.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class EhCacheBasedUserCache implements UserCache, InitializingBean,
+ DisposableBean {
+ //~ Static fields/initializers =============================================
+
+ private static final Log logger = LogFactory.getLog(EhCacheBasedUserCache.class);
+ private static final String CACHE_NAME = "ehCacheBasedUserCache";
+
+ //~ Instance fields ========================================================
+
+ private Cache cache;
+ private CacheManager manager;
+ private int minutesToIdle = 5;
+
+ //~ Methods ================================================================
+
+ public void setMinutesToIdle(int minutesToIdle) {
+ this.minutesToIdle = minutesToIdle;
+ }
+
+ /**
+ * Specifies how many minutes an entry will remain in the cache from when
+ * it was last accessed. This is effectively the session duration.
+ *
+ *
+ * Defaults to 5 minutes.
+ *
+ *
+ * @return Returns the minutes an element remains in the cache
+ */
+ public int getMinutesToIdle() {
+ return minutesToIdle;
+ }
+
+ public User getUserFromCache(String username) {
+ Element element = null;
+
+ try {
+ element = cache.get(username);
+ } catch (CacheException cacheException) {
+ throw new DataRetrievalFailureException("Cache failure: "
+ + cacheException.getMessage());
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Cache hit: " + (element != null) + "; username: "
+ + username);
+ }
+
+ if (element == null) {
+ return null;
+ } else {
+ return (User) element.getValue();
+ }
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ if (CacheManager.getInstance().cacheExists(CACHE_NAME)) {
+ CacheManager.getInstance().removeCache(CACHE_NAME);
+ }
+
+ manager = CacheManager.create();
+
+ // Cache name, max memory, overflowToDisk, eternal, timeToLive, timeToIdle
+ cache = new Cache(CACHE_NAME, Integer.MAX_VALUE, false, false,
+ minutesToIdle * 60, minutesToIdle * 60);
+ manager.addCache(cache);
+ }
+
+ public void destroy() throws Exception {
+ manager.removeCache(CACHE_NAME);
+ }
+
+ public void putUserInCache(User user) {
+ Element element = new Element(user.getUsername(), user);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Cache put: " + element.getKey());
+ }
+
+ cache.put(element);
+ }
+
+ public void removeUserFromCache(User user) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Cache remove: " + user.getUsername());
+ }
+
+ this.removeUserFromCache(user.getUsername());
+ }
+
+ public void removeUserFromCache(String username) {
+ cache.remove(username);
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/providers/dao/cache/NullUserCache.java b/core/src/main/java/org/acegisecurity/providers/dao/cache/NullUserCache.java
new file mode 100644
index 0000000000..26357d959e
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/providers/dao/cache/NullUserCache.java
@@ -0,0 +1,36 @@
+/* Copyright 2004 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.cache;
+
+import net.sf.acegisecurity.providers.dao.User;
+import net.sf.acegisecurity.providers.dao.UserCache;
+
+
+/**
+ * Does not perform any caching.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class NullUserCache implements UserCache {
+ //~ Methods ================================================================
+
+ public User getUserFromCache(String username) {
+ return null;
+ }
+
+ public void putUserInCache(User user) {}
+}
diff --git a/core/src/main/java/org/acegisecurity/providers/dao/cache/package.html b/core/src/main/java/org/acegisecurity/providers/dao/cache/package.html
new file mode 100644
index 0000000000..b59b1e93f2
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/providers/dao/cache/package.html
@@ -0,0 +1,5 @@
+
+
+Caches User objects for the DaoAuthenticationProvider.
+
+
diff --git a/core/src/test/java/org/acegisecurity/adapters/adaptertest-valid.xml b/core/src/test/java/org/acegisecurity/adapters/adaptertest-valid.xml
index 7f0c51c608..38a23ee9ca 100644
--- a/core/src/test/java/org/acegisecurity/adapters/adaptertest-valid.xml
+++ b/core/src/test/java/org/acegisecurity/adapters/adaptertest-valid.xml
@@ -36,7 +36,6 @@
- my_password
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 4404da03ee..6941bc4d6d 100644
--- a/core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationProviderTests.java
+++ b/core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationProviderTests.java
@@ -25,13 +25,16 @@ import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.providers.TestingAuthenticationToken;
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
+import net.sf.acegisecurity.providers.dao.cache.EhCacheBasedUserCache;
+import net.sf.acegisecurity.providers.dao.cache.NullUserCache;
import net.sf.acegisecurity.providers.dao.salt.SystemWideSaltSource;
import net.sf.acegisecurity.providers.encoding.ShaPasswordEncoder;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataRetrievalFailureException;
-import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
/**
@@ -56,8 +59,8 @@ public class DaoAuthenticationProviderTests extends TestCase {
"KOala");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
- provider.setKey("x");
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
+ provider.setUserCache(new MockUserCache());
try {
provider.authenticate(token);
@@ -72,8 +75,8 @@ public class DaoAuthenticationProviderTests extends TestCase {
"opal");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
- provider.setKey("x");
provider.setAuthenticationDao(new MockAuthenticationDaoUserPeter());
+ provider.setUserCache(new MockUserCache());
try {
provider.authenticate(token);
@@ -88,8 +91,8 @@ public class DaoAuthenticationProviderTests extends TestCase {
"koala");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
- provider.setKey("x");
provider.setAuthenticationDao(new MockAuthenticationDaoSimulateBackendError());
+ provider.setUserCache(new MockUserCache());
try {
provider.authenticate(token);
@@ -104,8 +107,8 @@ public class DaoAuthenticationProviderTests extends TestCase {
"INVALID_PASSWORD");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
- provider.setKey("x");
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
+ provider.setUserCache(new MockUserCache());
try {
provider.authenticate(token);
@@ -120,8 +123,8 @@ public class DaoAuthenticationProviderTests extends TestCase {
"koala");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
- provider.setKey("x");
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
+ provider.setUserCache(new MockUserCache());
try {
provider.authenticate(token);
@@ -136,8 +139,8 @@ public class DaoAuthenticationProviderTests extends TestCase {
"koala");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
- provider.setKey("x");
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
+ provider.setUserCache(new MockUserCache());
try {
provider.authenticate(token);
@@ -152,55 +155,21 @@ public class DaoAuthenticationProviderTests extends TestCase {
"koala");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
- provider.setKey("x");
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
+ provider.setUserCache(new MockUserCache());
Authentication result = provider.authenticate(token);
- if (!(result instanceof DaoAuthenticationToken)) {
- fail("Should have returned instance of DaoAuthenticationToken");
+ if (!(result instanceof UsernamePasswordAuthenticationToken)) {
+ fail(
+ "Should have returned instance of UsernamePasswordAuthenticationToken");
}
- DaoAuthenticationToken castResult = (DaoAuthenticationToken) result;
+ UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result;
assertEquals("marissa", castResult.getPrincipal());
assertEquals("koala", castResult.getCredentials());
assertEquals("ROLE_ONE", castResult.getAuthorities()[0].getAuthority());
assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority());
- assertEquals(provider.getKey().hashCode(), castResult.getKeyHash());
- }
-
- public void testAuthenticatesThenAcceptsCreatedTokenAutomatically() {
- UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa",
- "koala");
-
- DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
- provider.setKey("x");
- provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
-
- Authentication result = provider.authenticate(token);
-
- if (!(result instanceof DaoAuthenticationToken)) {
- fail("Should have returned instance of DaoAuthenticationToken");
- }
-
- DaoAuthenticationToken castResult = (DaoAuthenticationToken) result;
- assertEquals("marissa", castResult.getPrincipal());
- assertEquals(provider.getKey().hashCode(), castResult.getKeyHash());
- assertTrue(castResult.getExpires().after(new Date()));
-
- // Now try to re-authenticate
- // Set provider to null, so we get a NullPointerException if it tries to re-authenticate
- provider.setAuthenticationDao(null);
-
- Authentication secondResult = provider.authenticate(result);
-
- if (!(secondResult instanceof DaoAuthenticationToken)) {
- fail("Should have returned instance of DaoAuthenticationToken");
- }
-
- // Should still have the same expiry time as original
- assertEquals(castResult.getExpires(),
- ((DaoAuthenticationToken) secondResult).getExpires());
}
public void testAuthenticatesWhenASaltIsUsed() {
@@ -211,77 +180,22 @@ public class DaoAuthenticationProviderTests extends TestCase {
salt.setSystemWideSalt("SYSTEM_SALT_VALUE");
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
- provider.setKey("x");
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissaWithSalt());
provider.setSaltSource(salt);
+ provider.setUserCache(new MockUserCache());
Authentication result = provider.authenticate(token);
- if (!(result instanceof DaoAuthenticationToken)) {
+ if (!(result instanceof UsernamePasswordAuthenticationToken)) {
fail(
- "Should have returned instance of DaoPasswordAuthenticationToken");
+ "Should have returned instance of UsernamePasswordAuthenticationToken");
}
- DaoAuthenticationToken castResult = (DaoAuthenticationToken) result;
+ UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result;
assertEquals("marissa", castResult.getPrincipal());
assertEquals("koala{SYSTEM_SALT_VALUE}", castResult.getCredentials());
assertEquals("ROLE_ONE", castResult.getAuthorities()[0].getAuthority());
assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority());
- assertEquals(provider.getKey().hashCode(), castResult.getKeyHash());
- }
-
- public void testDaoAuthenticationTokensThatHaveExpiredAreRefreshed()
- throws Exception {
- UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa",
- "koala");
-
- DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
- provider.setKey("x");
- provider.setRefreshTokenInterval(0); // never cache
- provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
-
- Authentication result = provider.authenticate(token);
-
- if (!(result instanceof DaoAuthenticationToken)) {
- fail("Should have returned instance of DaoAuthenticationToken");
- }
-
- DaoAuthenticationToken castResult = (DaoAuthenticationToken) result;
- assertEquals("marissa", castResult.getPrincipal());
- assertEquals(provider.getKey().hashCode(), castResult.getKeyHash());
- Thread.sleep(1000);
- assertTrue(castResult.getExpires().before(new Date())); // already expired
-
- // Now try to re-authenticate
- Authentication secondResult = provider.authenticate(result);
-
- if (!(secondResult instanceof DaoAuthenticationToken)) {
- fail("Should have returned instance of DaoAuthenticationToken");
- }
-
- // Should still have a later expiry time than original
- assertTrue(castResult.getExpires().before(((DaoAuthenticationToken) secondResult)
- .getExpires()));
- }
-
- public void testDaoAuthenticationTokensWithWrongKeyAreRejected()
- throws Exception {
- DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
- provider.setKey("x");
- provider.setRefreshTokenInterval(0); // never cache
- provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
-
- DaoAuthenticationToken token = new DaoAuthenticationToken("key",
- new Date(), "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
-
- try {
- provider.authenticate(token);
- fail("Should have thrown BadCredentialsException");
- } catch (BadCredentialsException expected) {
- assertTrue(true);
- }
}
public void testGettersSetters() {
@@ -293,12 +207,15 @@ public class DaoAuthenticationProviderTests extends TestCase {
provider.setSaltSource(new SystemWideSaltSource());
assertEquals(SystemWideSaltSource.class,
provider.getSaltSource().getClass());
+
+ provider.setUserCache(new EhCacheBasedUserCache());
+ assertEquals(EhCacheBasedUserCache.class,
+ provider.getUserCache().getClass());
}
public void testStartupFailsIfNoAuthenticationDao()
throws Exception {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
- provider.setKey("xxx");
try {
provider.afterPropertiesSet();
@@ -308,9 +225,11 @@ public class DaoAuthenticationProviderTests extends TestCase {
}
}
- public void testStartupFailsIfNoKeySet() throws Exception {
+ public void testStartupFailsIfNoUserCacheSet() throws Exception {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setAuthenticationDao(new MockAuthenticationDaoUserMarissa());
+ assertEquals(NullUserCache.class, provider.getUserCache().getClass());
+ provider.setUserCache(null);
try {
provider.afterPropertiesSet();
@@ -323,8 +242,8 @@ public class DaoAuthenticationProviderTests extends TestCase {
public void testStartupSuccess() throws Exception {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
AuthenticationDao dao = new MockAuthenticationDaoUserMarissa();
- provider.setKey("x");
provider.setAuthenticationDao(dao);
+ provider.setUserCache(new MockUserCache());
assertEquals(dao, provider.getAuthenticationDao());
provider.afterPropertiesSet();
assertTrue(true);
@@ -334,7 +253,6 @@ public class DaoAuthenticationProviderTests extends TestCase {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
assertTrue(provider.supports(UsernamePasswordAuthenticationToken.class));
assertTrue(!provider.supports(TestingAuthenticationToken.class));
- assertTrue(provider.supports(DaoAuthenticationToken.class));
}
//~ Inner Classes ==========================================================
@@ -390,4 +308,16 @@ public class DaoAuthenticationProviderTests extends TestCase {
}
}
}
+
+ private class MockUserCache implements UserCache {
+ private Map cache = new HashMap();
+
+ public User getUserFromCache(String username) {
+ return (User) cache.get(username);
+ }
+
+ public void putUserInCache(User user) {
+ cache.put(user.getUsername(), user);
+ }
+ }
}
diff --git a/core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationTokenTests.java b/core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationTokenTests.java
deleted file mode 100644
index 0ce784c038..0000000000
--- a/core/src/test/java/org/acegisecurity/providers/dao/DaoAuthenticationTokenTests.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/* Copyright 2004 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;
-
-import junit.framework.TestCase;
-
-import net.sf.acegisecurity.GrantedAuthority;
-import net.sf.acegisecurity.GrantedAuthorityImpl;
-import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
-
-import java.util.Date;
-
-
-/**
- * Tests {@link DaoAuthenticationToken}.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class DaoAuthenticationTokenTests extends TestCase {
- //~ Constructors ===========================================================
-
- public DaoAuthenticationTokenTests() {
- super();
- }
-
- public DaoAuthenticationTokenTests(String arg0) {
- super(arg0);
- }
-
- //~ Methods ================================================================
-
- public final void setUp() throws Exception {
- super.setUp();
- }
-
- public static void main(String[] args) {
- junit.textui.TestRunner.run(DaoAuthenticationTokenTests.class);
- }
-
- public void testConstructorRejectsNulls() {
- try {
- new DaoAuthenticationToken(null, new Date(), "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException expected) {
- assertTrue(true);
- }
-
- try {
- new DaoAuthenticationToken("key", null, "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException expected) {
- assertTrue(true);
- }
-
- try {
- new DaoAuthenticationToken("key", new Date(), null, "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException expected) {
- assertTrue(true);
- }
-
- try {
- new DaoAuthenticationToken("key", new Date(), "Test", null,
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException expected) {
- assertTrue(true);
- }
-
- try {
- new DaoAuthenticationToken("key", new Date(), "Test", "Password",
- null);
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException expected) {
- assertTrue(true);
- }
-
- try {
- new DaoAuthenticationToken("key", new Date(), "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), null});
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException expected) {
- assertTrue(true);
- }
- }
-
- public void testEqualsWhenEqual() {
- Date date = new Date();
-
- DaoAuthenticationToken token1 = new DaoAuthenticationToken("key", date,
- "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
-
- DaoAuthenticationToken token2 = new DaoAuthenticationToken("key", date,
- "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
-
- assertEquals(token1, token2);
- }
-
- public void testGetters() {
- Date date = new Date();
- DaoAuthenticationToken token = new DaoAuthenticationToken("key", date,
- "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
- assertEquals("key".hashCode(), token.getKeyHash());
- assertEquals("Test", token.getPrincipal());
- assertEquals("Password", token.getCredentials());
- assertEquals("ROLE_ONE", token.getAuthorities()[0].getAuthority());
- assertEquals("ROLE_TWO", token.getAuthorities()[1].getAuthority());
- assertEquals(date, token.getExpires());
- }
-
- public void testNoArgConstructor() {
- try {
- new DaoAuthenticationToken();
- fail("Should have thrown IllegalArgumentException");
- } catch (IllegalArgumentException expected) {
- assertTrue(true);
- }
- }
-
- public void testNotEqualsDueToAbstractParentEqualsCheck() {
- Date date = new Date();
-
- DaoAuthenticationToken token1 = new DaoAuthenticationToken("key", date,
- "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
-
- DaoAuthenticationToken token2 = new DaoAuthenticationToken("key", date,
- "DIFFERENT_PRINCIPAL", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
-
- assertTrue(!token1.equals(token2));
- }
-
- public void testNotEqualsDueToDifferentAuthenticationClass() {
- DaoAuthenticationToken token1 = new DaoAuthenticationToken("key",
- new Date(), "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
-
- UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken("Test",
- "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
- token2.setAuthenticated(true);
-
- assertTrue(!token1.equals(token2));
- }
-
- public void testNotEqualsDueToDifferentExpiresDate() {
- DaoAuthenticationToken token1 = new DaoAuthenticationToken("key",
- new Date(50000), "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
-
- DaoAuthenticationToken token2 = new DaoAuthenticationToken("key",
- new Date(60000), "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
-
- assertTrue(!token1.equals(token2));
- }
-
- public void testNotEqualsDueToKey() {
- Date date = new Date();
-
- DaoAuthenticationToken token1 = new DaoAuthenticationToken("key", date,
- "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
-
- DaoAuthenticationToken token2 = new DaoAuthenticationToken("DIFFERENT_KEY",
- date, "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
-
- assertTrue(!token1.equals(token2));
- }
-
- public void testSetAuthenticatedIgnored() {
- DaoAuthenticationToken token = new DaoAuthenticationToken("key",
- new Date(), "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
- assertTrue(token.isAuthenticated());
- token.setAuthenticated(false); // ignored
- assertTrue(token.isAuthenticated());
- }
-
- public void testToString() {
- DaoAuthenticationToken token = new DaoAuthenticationToken("key",
- new Date(), "Test", "Password",
- new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
- "ROLE_TWO")});
- String result = token.toString();
- assertTrue(result.lastIndexOf("Expires:") != -1);
- }
-}
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
new file mode 100644
index 0000000000..4c99535dd1
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/providers/dao/cache/EhCacheBasedUserCacheTests.java
@@ -0,0 +1,83 @@
+/* Copyright 2004 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.cache;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.GrantedAuthority;
+import net.sf.acegisecurity.GrantedAuthorityImpl;
+import net.sf.acegisecurity.providers.dao.User;
+
+
+/**
+ * Tests {@link EhCacheBasedUserCache}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class EhCacheBasedUserCacheTests extends TestCase {
+ //~ Constructors ===========================================================
+
+ public EhCacheBasedUserCacheTests() {
+ super();
+ }
+
+ public EhCacheBasedUserCacheTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(EhCacheBasedUserCacheTests.class);
+ }
+
+ public void testCacheOperation() throws Exception {
+ EhCacheBasedUserCache cache = new EhCacheBasedUserCache();
+ cache.afterPropertiesSet();
+
+ // Check it gets stored in the cache
+ cache.putUserInCache(getUser());
+ assertEquals(getUser().getPassword(),
+ cache.getUserFromCache(getUser().getUsername()).getPassword());
+
+ // Check it gets removed from the cache
+ cache.removeUserFromCache(getUser());
+ assertNull(cache.getUserFromCache(getUser().getUsername()));
+
+ // Check it doesn't return values for null or unknown users
+ assertNull(cache.getUserFromCache(null));
+ assertNull(cache.getUserFromCache("UNKNOWN_USER"));
+
+ cache.destroy();
+ }
+
+ public void testGettersSetters() {
+ EhCacheBasedUserCache cache = new EhCacheBasedUserCache();
+ cache.setMinutesToIdle(15);
+ assertEquals(15, cache.getMinutesToIdle());
+ }
+
+ private User getUser() {
+ return new User("john", "password", 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
new file mode 100644
index 0000000000..477cace3bd
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/providers/dao/cache/NullUserCacheTests.java
@@ -0,0 +1,63 @@
+/* Copyright 2004 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.cache;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.GrantedAuthority;
+import net.sf.acegisecurity.GrantedAuthorityImpl;
+import net.sf.acegisecurity.providers.dao.User;
+
+
+/**
+ * Tests {@link NullUserCache}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class NullUserCacheTests extends TestCase {
+ //~ Constructors ===========================================================
+
+ public NullUserCacheTests() {
+ super();
+ }
+
+ public NullUserCacheTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(NullUserCacheTests.class);
+ }
+
+ public void testCacheOperation() throws Exception {
+ NullUserCache cache = new NullUserCache();
+ cache.putUserInCache(getUser());
+ assertNull(cache.getUserFromCache(null));
+ }
+
+ private User getUser() {
+ return new User("john", "password", true,
+ new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
+ "ROLE_TWO")});
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/ui/basicauth/filtertest-valid.xml b/core/src/test/java/org/acegisecurity/ui/basicauth/filtertest-valid.xml
index b9bd6b67bc..08c20c8af0 100644
--- a/core/src/test/java/org/acegisecurity/ui/basicauth/filtertest-valid.xml
+++ b/core/src/test/java/org/acegisecurity/ui/basicauth/filtertest-valid.xml
@@ -36,7 +36,6 @@
- my_password
diff --git a/docs/reference/src/index.xml b/docs/reference/src/index.xml
index 9ffb267c9b..da514e821d 100644
--- a/docs/reference/src/index.xml
+++ b/docs/reference/src/index.xml
@@ -892,7 +892,6 @@
<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
- <property name="key"><value>my_password</value></property>
<property name="refreshTokenInterval"><value>60000</value></property>
<property name="saltSource"><ref bean="saltSource"/></property>
<property name="passwordEncoder"><ref bean="passwordEncoder"/></property>
@@ -910,23 +909,30 @@
SaltSource implementations are also provided:
SystemWideSaltSource which encodes all passwords
with the same salt, and ReflectionSaltSource, which
- inspects a given property of the returned User object to obtain the
- salt. Please refer to the JavaDocs for further details on these
- optional features.
+ inspects a given property of the returned User
+ object to obtain the salt. Please refer to the JavaDocs for further
+ details on these optional features.
- The key property permits the
- DaoAuthenticationProvider to build a
- DaoAuthenticationToken that represents the
- successful authentication request. This allows the
- DaoAuthenticationProvider to avoid repeated lookups
- of the backend authentication repository. For a presented
- DaoAuthenticationToken to be accepted as valid, it
- needs to both present the expected key (to prove it was created by the
- DaoAuthenticationProvider) and that is has not
- expired. DaoAuthenticationTokens by default expire
- 60 seconds after they have been created, although this can be set to
- any other millisecond value via the
- refreshTokenInterval property.
+ In addition to the properties above, the
+ DaoAuthenticationProvider supports optional caching
+ of User objects. The UserCache
+ interface enables the DaoAuthenticationProvider to
+ place a User object into the cache, and retrieve it
+ from the cache upon subsequent authentication attempts for the same
+ username. By default the DaoAuthenticationProvider
+ uses the NullUserCache, which performs no caching.
+ A usable caching implementation is also provided,
+ EhCacheBasedUserCache, which is configured as
+ follows:
+
+ <bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
+ <property name="authenticationDao"><ref bean="authenticationDao"/></property>
+ <property name="userCache"><ref bean="userCache"/></property>
+</bean>
+
+<bean id="userCache" class="net.sf.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
+ <property name="minutesToIdle"><value>5</value></property>
+</bean>
For a class to be able to provide the
DaoAuthenticationProvider with access to an
diff --git a/samples/contacts/build.xml b/samples/contacts/build.xml
index 70077351e4..0578331421 100644
--- a/samples/contacts/build.xml
+++ b/samples/contacts/build.xml
@@ -152,6 +152,8 @@
+
+
diff --git a/samples/contacts/etc/ca/applicationContext.xml b/samples/contacts/etc/ca/applicationContext.xml
index 48906619eb..46802b2516 100644
--- a/samples/contacts/etc/ca/applicationContext.xml
+++ b/samples/contacts/etc/ca/applicationContext.xml
@@ -48,7 +48,6 @@
- my_password
diff --git a/samples/contacts/etc/filter/applicationContext.xml b/samples/contacts/etc/filter/applicationContext.xml
index ffbce7886e..ddbb18a1ab 100644
--- a/samples/contacts/etc/filter/applicationContext.xml
+++ b/samples/contacts/etc/filter/applicationContext.xml
@@ -43,7 +43,11 @@
- my_password
+
+
+
+
+ 5
diff --git a/samples/quick-start/war-root/WEB-INF/applicationContext.xml b/samples/quick-start/war-root/WEB-INF/applicationContext.xml
index b3f4e2362d..3ac87fe5b6 100644
--- a/samples/quick-start/war-root/WEB-INF/applicationContext.xml
+++ b/samples/quick-start/war-root/WEB-INF/applicationContext.xml
@@ -42,11 +42,14 @@
-
- my_password
+
+
+
+
+ 5