Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- @Service
- public class CustomPersistentRememberMeServices extends
- AbstractRememberMeServices {
- private final Logger log = LoggerFactory.getLogger(CustomPersistentRememberMeServices.class);
- // Token is valid for one month
- private static final int TOKEN_VALIDITY_DAYS = 31;
- private static final int TOKEN_VALIDITY_SECONDS = 60 * 60 * 24 * TOKEN_VALIDITY_DAYS;
- private static final int DEFAULT_SERIES_LENGTH = 16;
- private static final int DEFAULT_TOKEN_LENGTH = 16;
- private SecureRandom random;
- @Inject
- private PersistentTokenRepository persistentTokenRepository;
- @Inject
- private UserRepository userRepository;
- @Inject
- public CustomPersistentRememberMeServices(Environment env, org.springframework.security.core.userdetails
- .UserDetailsService userDetailsService) {
- super(env.getProperty("jhipster.security.rememberme.key"), userDetailsService);
- random = new SecureRandom();
- }
- @Override
- @Transactional
- protected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request,
- HttpServletResponse response) {
- PersistentToken token = getPersistentToken(cookieTokens);
- String login = token.getUser().getSteamId();
- // Token also matches, so login is valid. Update the token value, keeping the *same* series number.
- log.debug("Refreshing persistent login token for user '{}', series '{}'", login, token.getSeries());
- token.setTokenDate(LocalDate.now());
- token.setTokenValue(generateTokenData());
- token.setIpAddress(request.getRemoteAddr());
- token.setUserAgent(request.getHeader("User-Agent"));
- try {
- persistentTokenRepository.saveAndFlush(token);
- addCookie(token, request, response);
- } catch (DataAccessException e) {
- log.error("Failed to update token: ", e);
- throw new RememberMeAuthenticationException("Autologin failed due to data access problem", e);
- }
- return getUserDetailsService().loadUserByUsername(login);
- }
- @Override
- protected void onLoginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication
- successfulAuthentication) {
- String steamId = Util.extractSteamId(successfulAuthentication.getName());
- log.debug("Creating new persistent login for user {}", steamId);
- PersistentToken token = userRepository.findOneBySteamId(steamId).map(u -> {
- PersistentToken t = new PersistentToken();
- t.setSeries(generateSeriesData());
- t.setUser(u);
- t.setTokenValue(generateTokenData());
- t.setTokenDate(LocalDate.now());
- t.setIpAddress(request.getRemoteAddr());
- t.setUserAgent(request.getHeader("User-Agent"));
- return t;
- }).orElseThrow(() -> new UsernameNotFoundException("User " + steamId + " was not found in the database"));
- try {
- persistentTokenRepository.saveAndFlush(token);
- addCookie(token, request, response);
- } catch (DataAccessException e) {
- log.error("Failed to save persistent token ", e);
- }
- }
- /**
- * When logout occurs, only invalidate the current token, and not all user sessions.
- * <p/>
- * The standard Spring Security implementations are too basic: they invalidate all tokens for the
- * current user, so when he logs out from one browser, all his other sessions are destroyed.
- */
- @Override
- @Transactional
- public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
- String rememberMeCookie = extractRememberMeCookie(request);
- if (rememberMeCookie != null && rememberMeCookie.length() != 0) {
- try {
- String[] cookieTokens = decodeCookie(rememberMeCookie);
- PersistentToken token = getPersistentToken(cookieTokens);
- persistentTokenRepository.delete(token);
- } catch (InvalidCookieException ice) {
- log.info("Invalid cookie, no persistent token could be deleted");
- } catch (RememberMeAuthenticationException rmae) {
- log.debug("No persistent token found, so no token could be deleted");
- }
- }
- super.logout(request, response, authentication);
- }
- /**
- * Validate the token and return it.
- */
- private PersistentToken getPersistentToken(String[] cookieTokens) {
- if (cookieTokens.length != 2) {
- throw new InvalidCookieException("Cookie token did not contain " + 2 +
- " tokens, but contained '" + Arrays.asList(cookieTokens) + "'");
- }
- String presentedSeries = cookieTokens[0];
- String presentedToken = cookieTokens[1];
- PersistentToken token = persistentTokenRepository.findOne(presentedSeries);
- if (token == null) {
- // No series match, so we can't authenticate using this cookie
- throw new RememberMeAuthenticationException("No persistent token found for series id: " + presentedSeries);
- }
- // We have a match for this user/series combination
- log.info("presentedToken={} / tokenValue={}", presentedToken, token.getTokenValue());
- if (!presentedToken.equals(token.getTokenValue())) {
- // Token doesn't match series value. Delete this session and throw an exception.
- persistentTokenRepository.delete(token);
- throw new CookieTheftException("Invalid remember-me token (Series/token) mismatch. Implies previous " +
- "cookie theft attack.");
- }
- if (token.getTokenDate().plusDays(TOKEN_VALIDITY_DAYS).isBefore(LocalDate.now())) {
- persistentTokenRepository.delete(token);
- throw new RememberMeAuthenticationException("Remember-me login has expired");
- }
- return token;
- }
- private String generateSeriesData() {
- byte[] newSeries = new byte[DEFAULT_SERIES_LENGTH];
- random.nextBytes(newSeries);
- return new String(Base64.encode(newSeries));
- }
- private String generateTokenData() {
- byte[] newToken = new byte[DEFAULT_TOKEN_LENGTH];
- random.nextBytes(newToken);
- return new String(Base64.encode(newToken));
- }
- private void addCookie(PersistentToken token, HttpServletRequest request, HttpServletResponse response) {
- setCookie(
- new String[]{token.getSeries(), token.getTokenValue()},
- TOKEN_VALIDITY_SECONDS, request, response);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement