Created
February 10, 2023 20:50
-
-
Save fedotxxl/7b7b74cb345536f02a6dea1e468c455f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ru.gramant.adplanner.auth; | |
import org.springframework.security.core.userdetails.UserDetails; | |
import org.springframework.security.core.userdetails.UserDetailsService; | |
import org.springframework.security.web.authentication.rememberme.*; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
import java.util.Arrays; | |
import java.util.Date; | |
import java.util.List; | |
public class CustomPersistentTokenBasedRememberMeServices extends PersistentTokenBasedRememberMeServices { | |
private CustomPersistentTokenRepository tokenRepository; | |
private int maxDurationInMs; | |
public CustomPersistentTokenBasedRememberMeServices( | |
String key, | |
UserDetailsService userDetailsService, | |
CustomPersistentTokenRepository tokenRepository, | |
int maxDurationInMs | |
) { | |
super(key, userDetailsService, tokenRepository); | |
this.tokenRepository = tokenRepository; | |
this.maxDurationInMs = maxDurationInMs; | |
} | |
protected UserDetails processAutoLoginCookie(String[] cookieTokens, | |
HttpServletRequest request, HttpServletResponse response) { | |
if (cookieTokens.length != 2) { | |
throw new InvalidCookieException("Cookie token did not contain " + 2 | |
+ " tokens, but contained '" + Arrays.asList(cookieTokens) + "'"); | |
} | |
final String presentedSeries = cookieTokens[0]; | |
final String presentedToken = cookieTokens[1]; | |
List<PersistentRememberMeToken> tokens = tokenRepository.findAllBySeries(presentedSeries); | |
if (tokens.isEmpty()) { | |
// No series match, so we can't authenticate using this cookie | |
throw new RememberMeAuthenticationException("No persistent token found for series id: " + presentedSeries); | |
} | |
PersistentRememberMeToken tokenLast = tokens.get(0); | |
PersistentRememberMeToken tokenCurrent = tokens.stream().filter(t -> presentedToken.equals(t.getTokenValue())).findFirst().orElse(null); | |
// We have a match for this user/series combination | |
if (tokenCurrent == null || ((tokenLast.getDate().getTime() - tokenCurrent.getDate().getTime()) > maxDurationInMs)) { | |
// Token doesn't match series value. Delete all logins for this user and throw | |
// an exception to warn them. | |
tokenRepository.removeUserTokens(tokenLast.getUsername()); | |
throw new CookieTheftException( | |
messages.getMessage( | |
"PersistentTokenBasedRememberMeServices.cookieStolen", | |
"Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack." | |
) | |
); | |
} | |
if (tokenLast.getDate().getTime() + getTokenValiditySeconds() * 1000L < System.currentTimeMillis()) { | |
throw new RememberMeAuthenticationException("Remember-me login has expired"); | |
} | |
// Token also matches, so login is valid. Update the token value, keeping the | |
// *same* series number. | |
if (logger.isDebugEnabled()) { | |
logger.debug("Refreshing persistent login token for user '" + tokenLast.getUsername() + "', series '" + tokenLast.getSeries() + "'"); | |
} | |
PersistentRememberMeToken newToken = new PersistentRememberMeToken( | |
tokenLast.getUsername(), | |
tokenLast.getSeries(), | |
generateTokenData(), | |
new Date() | |
); | |
try { | |
tokenRepository.createNewToken(newToken); | |
addCookie(newToken, request, response); | |
} catch (Exception e) { | |
logger.error("Failed to update token: ", e); | |
throw new RememberMeAuthenticationException( | |
"Autologin failed due to data access problem"); | |
} | |
return getUserDetailsService().loadUserByUsername(tokenLast.getUsername()); | |
} | |
private void addCookie( | |
PersistentRememberMeToken token, | |
HttpServletRequest request, | |
HttpServletResponse response | |
) { | |
setCookie( | |
new String[]{token.getSeries(), token.getTokenValue()}, | |
getTokenValiditySeconds(), | |
request, | |
response | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment