Make User available from Authentication via DaoAuthenticationProvider.
This commit is contained in:
@@ -51,12 +51,26 @@ import org.springframework.dao.DataAccessException;
|
||||
* <p>
|
||||
* Upon successful validation, a
|
||||
* <code>UsernamePasswordAuthenticationToken</code> 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.
|
||||
* returned to the caller. The token will include as its principal either a
|
||||
* <code>String</code> representation of the username, or the {@link User}
|
||||
* that was returned from the authentication repository. Using
|
||||
* <code>String</code> is appropriate if a container adapter is being used, as
|
||||
* it expects <code>String</code> representations of the username. Using
|
||||
* <code>User</code> is appropriate if you require access to additional
|
||||
* properties of the authenticated user, such as email addresses,
|
||||
* human-friendly names etc. As container adapters are not recommended to be
|
||||
* used, and <code>User</code> provides additional flexibility, by default a
|
||||
* <code>User</code> is returned. To override this default, set the {@link
|
||||
* #setForcePrincipalAsString} to <code>true</code>.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* Caching is handled via the <code>User</code> object being placed in the
|
||||
* {@link UserCache}. This ensures 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.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
@@ -79,6 +93,7 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
||||
private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();
|
||||
private SaltSource saltSource;
|
||||
private UserCache userCache = new NullUserCache();
|
||||
private boolean forcePrincipalAsString = false;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
@@ -95,6 +110,14 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
||||
return authenticationDao;
|
||||
}
|
||||
|
||||
public void setForcePrincipalAsString(boolean forcePrincipalAsString) {
|
||||
this.forcePrincipalAsString = forcePrincipalAsString;
|
||||
}
|
||||
|
||||
public boolean isForcePrincipalAsString() {
|
||||
return forcePrincipalAsString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the PasswordEncoder instance to be used to encode and validate
|
||||
* passwords. If not set, {@link PlaintextPasswordEncoder} will be used by
|
||||
@@ -148,13 +171,19 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
||||
|
||||
public Authentication authenticate(Authentication authentication)
|
||||
throws AuthenticationException {
|
||||
// Determine username
|
||||
String username = authentication.getPrincipal().toString();
|
||||
|
||||
if (authentication.getPrincipal() instanceof User) {
|
||||
username = ((User) authentication.getPrincipal()).getUsername();
|
||||
}
|
||||
|
||||
boolean cacheWasUsed = true;
|
||||
User user = this.userCache.getUserFromCache(authentication.getPrincipal()
|
||||
.toString());
|
||||
User user = this.userCache.getUserFromCache(username);
|
||||
|
||||
if (user == null) {
|
||||
cacheWasUsed = false;
|
||||
user = getUserFromBackend(authentication);
|
||||
user = getUserFromBackend(username);
|
||||
}
|
||||
|
||||
if (!user.isEnabled()) {
|
||||
@@ -170,7 +199,7 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
||||
// Password incorrect, so ensure we're using most current password
|
||||
if (cacheWasUsed) {
|
||||
cacheWasUsed = false;
|
||||
user = getUserFromBackend(authentication);
|
||||
user = getUserFromBackend(username);
|
||||
}
|
||||
|
||||
if (!isPasswordCorrect(authentication, user)) {
|
||||
@@ -194,9 +223,15 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
||||
}
|
||||
}
|
||||
|
||||
Object principalToReturn = user;
|
||||
|
||||
if (forcePrincipalAsString) {
|
||||
principalToReturn = user.getUsername();
|
||||
}
|
||||
|
||||
// Ensure we return the original credentials the user supplied,
|
||||
// so subsequent attempts are successful even with encoded passwords
|
||||
return new UsernamePasswordAuthenticationToken(user.getUsername(),
|
||||
return new UsernamePasswordAuthenticationToken(principalToReturn,
|
||||
authentication.getCredentials(), user.getAuthorities());
|
||||
}
|
||||
|
||||
@@ -220,10 +255,9 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
||||
authentication.getCredentials().toString(), salt);
|
||||
}
|
||||
|
||||
private User getUserFromBackend(Authentication authentication) {
|
||||
private User getUserFromBackend(String username) {
|
||||
try {
|
||||
return this.authenticationDao.loadUserByUsername(authentication.getPrincipal()
|
||||
.toString());
|
||||
return this.authenticationDao.loadUserByUsername(username);
|
||||
} catch (UsernameNotFoundException notFound) {
|
||||
throw new BadCredentialsException("Bad credentials presented");
|
||||
} catch (DataAccessException repositoryProblem) {
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<!-- Authentication provider that queries our data access object -->
|
||||
<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
|
||||
<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
|
||||
<property name="forcePrincipalAsString"><value>true</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- The authentication manager that iterates through our only authentication provider -->
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<!-- Authentication provider that queries our data access object -->
|
||||
<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
|
||||
<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
|
||||
<property name="forcePrincipalAsString"><value>true</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- The authentication manager that iterates through our only authentication provider -->
|
||||
|
||||
@@ -166,7 +166,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
|
||||
}
|
||||
|
||||
UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result;
|
||||
assertEquals("marissa", castResult.getPrincipal());
|
||||
assertEquals(User.class, castResult.getPrincipal().getClass());
|
||||
assertEquals("koala", castResult.getCredentials());
|
||||
assertEquals("ROLE_ONE", castResult.getAuthorities()[0].getAuthority());
|
||||
assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority());
|
||||
@@ -192,7 +192,7 @@ public class DaoAuthenticationProviderTests extends TestCase {
|
||||
}
|
||||
|
||||
UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result;
|
||||
assertEquals("marissa", castResult.getPrincipal());
|
||||
assertEquals(User.class, castResult.getPrincipal().getClass());
|
||||
|
||||
// We expect original credentials user submitted to be returned
|
||||
assertEquals("koala", castResult.getCredentials());
|
||||
|
||||
@@ -24,6 +24,7 @@ import net.sf.acegisecurity.MockFilterConfig;
|
||||
import net.sf.acegisecurity.MockHttpServletRequest;
|
||||
import net.sf.acegisecurity.MockHttpServletResponse;
|
||||
import net.sf.acegisecurity.MockHttpSession;
|
||||
import net.sf.acegisecurity.providers.dao.User;
|
||||
import net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
@@ -199,8 +200,8 @@ public class BasicProcessingFilterTests extends TestCase {
|
||||
|
||||
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) != null);
|
||||
assertEquals("marissa",
|
||||
((Authentication) request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY)).getPrincipal()
|
||||
.toString());
|
||||
((User) ((Authentication) request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY)).getPrincipal())
|
||||
.getUsername());
|
||||
}
|
||||
|
||||
public void testOtherAuthorizationSchemeIsIgnored()
|
||||
@@ -291,8 +292,8 @@ public class BasicProcessingFilterTests extends TestCase {
|
||||
|
||||
assertTrue(request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY) != null);
|
||||
assertEquals("marissa",
|
||||
((Authentication) request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY)).getPrincipal()
|
||||
.toString());
|
||||
((User) ((Authentication) request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY)).getPrincipal())
|
||||
.getUsername());
|
||||
|
||||
// NOW PERFORM FAILED AUTHENTICATION
|
||||
// Setup our HTTP request
|
||||
|
||||
@@ -20,6 +20,8 @@ import junit.framework.TestCase;
|
||||
import net.sf.acegisecurity.MockHttpServletRequest;
|
||||
import net.sf.acegisecurity.MockHttpServletResponse;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link CasProcessingFilterEntryPoint}.
|
||||
@@ -99,8 +101,11 @@ public class CasProcessingFilterEntryPointTests extends TestCase {
|
||||
|
||||
ep.afterPropertiesSet();
|
||||
ep.commence(request, response);
|
||||
assertEquals("https://cas/login?service=https://mycompany.com/bigWebApp/j_acegi_cas_security_check",
|
||||
response.getRedirect());
|
||||
|
||||
assertEquals("https://cas/login?service="
|
||||
+ URLEncoder.encode(
|
||||
"https://mycompany.com/bigWebApp/j_acegi_cas_security_check",
|
||||
"UTF-8"), response.getRedirect());
|
||||
}
|
||||
|
||||
public void testNormalOperationWithRenewTrue() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user