Improved comments and made TokenBasedRememberMeServices modular to support subclasses
This commit is contained in:
@@ -127,7 +127,8 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
* @version $Id: AbstractProcessingFilter.java 1909 2007-06-19 04:08:19Z
|
||||
* vishalpuri $
|
||||
*/
|
||||
public abstract class AbstractProcessingFilter implements Filter, InitializingBean, ApplicationEventPublisherAware,
|
||||
MessageSourceAware, ApplicationContextAware {
|
||||
@@ -224,12 +225,15 @@ public abstract class AbstractProcessingFilter implements Filter, InitializingBe
|
||||
Assert.notNull(this.rememberMeServices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the first autodetected instance of <code>RememberMeServices</code>
|
||||
*/
|
||||
private void autoDetectRememberMeServices() {
|
||||
if (applicationContext != null) {
|
||||
Map map = applicationContext.getBeansOfType(RememberMeServices.class);
|
||||
if (map.size() > 0) {
|
||||
setRememberMeServices((RememberMeServices) map.values().iterator().next());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+92
-42
@@ -105,12 +105,11 @@ import org.springframework.web.bind.RequestUtils;
|
||||
* @version $Id: TokenBasedRememberMeServices.java 1871 2007-05-25 03:12:49Z
|
||||
* benalex $
|
||||
*/
|
||||
public class TokenBasedRememberMeServices implements RememberMeServices, InitializingBean, LogoutHandler, Ordered, ApplicationContextAware {
|
||||
public class TokenBasedRememberMeServices implements RememberMeServices, InitializingBean, LogoutHandler, Ordered,
|
||||
ApplicationContextAware {
|
||||
// ~ Static fields/initializers
|
||||
// =====================================================================================
|
||||
|
||||
|
||||
|
||||
public static final String ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY = "ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE";
|
||||
|
||||
public static final String DEFAULT_PARAMETER = "_acegi_security_remember_me";
|
||||
@@ -149,13 +148,14 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
Assert.hasLength(key);
|
||||
Assert.hasLength(parameter);
|
||||
Assert.hasLength(cookieName);
|
||||
Assert.notNull(applicationContext, "ApplicationContext required");
|
||||
if (!isSetUserDetailsServiceInvoked) {
|
||||
autoDetectAnyUserDetailsServiceAndUseIt(applicationContext);
|
||||
if (applicationContext != null) {
|
||||
if (!isSetUserDetailsServiceInvoked) {
|
||||
autoDetectAndUseAnyUserDetailsService(applicationContext);
|
||||
}
|
||||
}
|
||||
Assert.notNull(userDetailsService);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Introspects the <code>Applicationcontext</code> for the single instance
|
||||
* of {@link AccessDeniedHandler}. If found invoke
|
||||
@@ -166,7 +166,7 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
*
|
||||
* @param applicationContext to locate the instance
|
||||
*/
|
||||
private void autoDetectAnyUserDetailsServiceAndUseIt(ApplicationContext applicationContext) {
|
||||
private void autoDetectAndUseAnyUserDetailsService(ApplicationContext applicationContext) {
|
||||
Map map = applicationContext.getBeansOfType(UserDetailsService.class);
|
||||
if (map.size() > 1) {
|
||||
throw new IllegalArgumentException(
|
||||
@@ -177,7 +177,6 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
setUserDetailsService((UserDetailsService) map.values().iterator().next());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) {
|
||||
Cookie[] cookies = request.getCookies();
|
||||
@@ -208,6 +207,7 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
String[] cookieTokens = StringUtils.delimitedListToStringArray(cookieAsPlainText, ":");
|
||||
|
||||
if (cookieTokens.length == 3) {
|
||||
|
||||
long tokenExpiryTime;
|
||||
|
||||
try {
|
||||
@@ -221,8 +221,7 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check it has not expired
|
||||
if (tokenExpiryTime < System.currentTimeMillis()) {
|
||||
if (isTokenExpired(tokenExpiryTime)) {
|
||||
cancelCookie(request, response, "Cookie token[1] has expired (expired on '"
|
||||
+ new Date(tokenExpiryTime) + "'; current time is '" + new Date() + "')");
|
||||
|
||||
@@ -232,25 +231,15 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
// Check the user exists
|
||||
// Defer lookup until after expiry time checked, to
|
||||
// possibly avoid expensive lookup
|
||||
UserDetails userDetails;
|
||||
UserDetails userDetails = loadUserDetails(request, response, cookieTokens);
|
||||
|
||||
try {
|
||||
userDetails = this.userDetailsService.loadUserByUsername(cookieTokens[0]);
|
||||
}
|
||||
catch (UsernameNotFoundException notFound) {
|
||||
if (userDetails == null) {
|
||||
cancelCookie(request, response, "Cookie token[0] contained username '" + cookieTokens[0]
|
||||
+ "' but was not found");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Immediately reject if the user is not allowed to
|
||||
// login
|
||||
if (!userDetails.isAccountNonExpired() || !userDetails.isCredentialsNonExpired()
|
||||
|| !userDetails.isEnabled()) {
|
||||
cancelCookie(request, response, "Cookie token[0] contained username '" + cookieTokens[0]
|
||||
+ "' but account has expired, credentials have expired, or user is disabled");
|
||||
|
||||
if (!isValidUserDetails(request, response, userDetails, cookieTokens)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -264,8 +253,7 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
// (as if the token is valid, it will cause
|
||||
// SecurityContextHolder population, whilst
|
||||
// if invalid, will cause the cookie to be cancelled)
|
||||
String expectedTokenSignature = DigestUtils.md5Hex(userDetails.getUsername() + ":"
|
||||
+ tokenExpiryTime + ":" + userDetails.getPassword() + ":" + this.key);
|
||||
String expectedTokenSignature = makeTokenSignature(tokenExpiryTime, userDetails);
|
||||
|
||||
if (!expectedTokenSignature.equals(cookieTokens[2])) {
|
||||
cancelCookie(request, response, "Cookie token[2] contained signature '" + cookieTokens[2]
|
||||
@@ -304,7 +292,55 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
return null;
|
||||
}
|
||||
|
||||
private void cancelCookie(HttpServletRequest request, HttpServletResponse response, String reasonForLog) {
|
||||
/**
|
||||
* @param tokenExpiryTime
|
||||
* @param userDetails
|
||||
* @return
|
||||
*/
|
||||
protected String makeTokenSignature(long tokenExpiryTime, UserDetails userDetails) {
|
||||
String expectedTokenSignature = DigestUtils.md5Hex(userDetails.getUsername() + ":" + tokenExpiryTime + ":"
|
||||
+ userDetails.getPassword() + ":" + this.key);
|
||||
return expectedTokenSignature;
|
||||
}
|
||||
|
||||
protected boolean isValidUserDetails(HttpServletRequest request, HttpServletResponse response,
|
||||
UserDetails userDetails, String[] cookieTokens) {
|
||||
// Immediately reject if the user is not allowed to
|
||||
// login
|
||||
if (!userDetails.isAccountNonExpired() || !userDetails.isCredentialsNonExpired() || !userDetails.isEnabled()) {
|
||||
cancelCookie(request, response, "Cookie token[0] contained username '" + cookieTokens[0]
|
||||
+ "' but account has expired, credentials have expired, or user is disabled");
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected UserDetails loadUserDetails(HttpServletRequest request, HttpServletResponse response,
|
||||
String[] cookieTokens) {
|
||||
UserDetails userDetails = null;
|
||||
|
||||
try {
|
||||
userDetails = this.userDetailsService.loadUserByUsername(cookieTokens[0]);
|
||||
}
|
||||
catch (UsernameNotFoundException notFound) {
|
||||
cancelCookie(request, response, "Cookie token[0] contained username '" + cookieTokens[0]
|
||||
+ "' but was not found");
|
||||
|
||||
return null;
|
||||
}
|
||||
return userDetails;
|
||||
}
|
||||
|
||||
protected boolean isTokenExpired(long tokenExpiryTime) {
|
||||
// Check it has not expired
|
||||
if (tokenExpiryTime < System.currentTimeMillis()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void cancelCookie(HttpServletRequest request, HttpServletResponse response, String reasonForLog) {
|
||||
if ((reasonForLog != null) && logger.isDebugEnabled()) {
|
||||
logger.debug("Cancelling cookie for reason: " + reasonForLog);
|
||||
}
|
||||
@@ -356,17 +392,8 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
Assert.notNull(successfulAuthentication.getPrincipal());
|
||||
Assert.notNull(successfulAuthentication.getCredentials());
|
||||
|
||||
String username;
|
||||
String password;
|
||||
|
||||
if (successfulAuthentication.getPrincipal() instanceof UserDetails) {
|
||||
username = ((UserDetails) successfulAuthentication.getPrincipal()).getUsername();
|
||||
password = ((UserDetails) successfulAuthentication.getPrincipal()).getPassword();
|
||||
}
|
||||
else {
|
||||
username = successfulAuthentication.getPrincipal().toString();
|
||||
password = successfulAuthentication.getCredentials().toString();
|
||||
}
|
||||
String username = retrieveUserName(successfulAuthentication);
|
||||
String password = retrievePassword(successfulAuthentication);
|
||||
|
||||
// If unable to find a username and password, just abort as
|
||||
// TokenBasedRememberMeServices unable to construct a valid token in
|
||||
@@ -375,9 +402,6 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.hasLength(username);
|
||||
Assert.hasLength(password);
|
||||
|
||||
long expiryTime = System.currentTimeMillis() + (tokenValiditySeconds * 1000);
|
||||
|
||||
// construct token to put in cookie; format is:
|
||||
@@ -400,6 +424,28 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
+ (authentication == null ? "Unknown" : authentication.getName()));
|
||||
}
|
||||
|
||||
protected String retrieveUserName(Authentication successfulAuthentication) {
|
||||
if (isInstanceOfUserDetails(successfulAuthentication)) {
|
||||
return ((UserDetails) successfulAuthentication.getPrincipal()).getUsername();
|
||||
}
|
||||
else {
|
||||
return successfulAuthentication.getPrincipal().toString();
|
||||
}
|
||||
}
|
||||
|
||||
protected String retrievePassword(Authentication successfulAuthentication) {
|
||||
if (isInstanceOfUserDetails(successfulAuthentication)) {
|
||||
return ((UserDetails) successfulAuthentication.getPrincipal()).getPassword();
|
||||
}
|
||||
else {
|
||||
return successfulAuthentication.getCredentials().toString();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInstanceOfUserDetails(Authentication authentication) {
|
||||
return authentication.getPrincipal() instanceof UserDetails;
|
||||
}
|
||||
|
||||
protected Cookie makeCancelCookie(HttpServletRequest request) {
|
||||
Cookie cookie = new Cookie(cookieName, null);
|
||||
cookie.setMaxAge(0);
|
||||
@@ -459,7 +505,11 @@ public class TokenBasedRememberMeServices implements RememberMeServices, Initial
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext=applicationContext;
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public String getCookieName() {
|
||||
return cookieName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user