Advertisement
Guest User

Untitled

a guest
Dec 17th, 2015
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.62 KB | None | 0 0
  1. @Service
  2. public class CustomPersistentRememberMeServices extends
  3.     AbstractRememberMeServices {
  4.  
  5.     private final Logger log = LoggerFactory.getLogger(CustomPersistentRememberMeServices.class);
  6.  
  7.     // Token is valid for one month
  8.     private static final int TOKEN_VALIDITY_DAYS = 31;
  9.  
  10.     private static final int TOKEN_VALIDITY_SECONDS = 60 * 60 * 24 * TOKEN_VALIDITY_DAYS;
  11.  
  12.     private static final int DEFAULT_SERIES_LENGTH = 16;
  13.  
  14.     private static final int DEFAULT_TOKEN_LENGTH = 16;
  15.  
  16.     private SecureRandom random;
  17.  
  18.     @Inject
  19.     private PersistentTokenRepository persistentTokenRepository;
  20.  
  21.     @Inject
  22.     private UserRepository userRepository;
  23.  
  24.     @Inject
  25.     public CustomPersistentRememberMeServices(Environment env, org.springframework.security.core.userdetails
  26.         .UserDetailsService userDetailsService) {
  27.  
  28.         super(env.getProperty("jhipster.security.rememberme.key"), userDetailsService);
  29.         random = new SecureRandom();
  30.     }
  31.  
  32.     @Override
  33.     @Transactional
  34.     protected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request,
  35.         HttpServletResponse response) {
  36.  
  37.         PersistentToken token = getPersistentToken(cookieTokens);
  38.         String login = token.getUser().getSteamId();
  39.  
  40.         // Token also matches, so login is valid. Update the token value, keeping the *same* series number.
  41.         log.debug("Refreshing persistent login token for user '{}', series '{}'", login, token.getSeries());
  42.         token.setTokenDate(LocalDate.now());
  43.         token.setTokenValue(generateTokenData());
  44.         token.setIpAddress(request.getRemoteAddr());
  45.         token.setUserAgent(request.getHeader("User-Agent"));
  46.         try {
  47.             persistentTokenRepository.saveAndFlush(token);
  48.             addCookie(token, request, response);
  49.         } catch (DataAccessException e) {
  50.             log.error("Failed to update token: ", e);
  51.             throw new RememberMeAuthenticationException("Autologin failed due to data access problem", e);
  52.         }
  53.         return getUserDetailsService().loadUserByUsername(login);
  54.     }
  55.  
  56.     @Override
  57.     protected void onLoginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication
  58.         successfulAuthentication) {
  59.  
  60.         String steamId = Util.extractSteamId(successfulAuthentication.getName());
  61.  
  62.         log.debug("Creating new persistent login for user {}", steamId);
  63.         PersistentToken token = userRepository.findOneBySteamId(steamId).map(u -> {
  64.             PersistentToken t = new PersistentToken();
  65.             t.setSeries(generateSeriesData());
  66.             t.setUser(u);
  67.             t.setTokenValue(generateTokenData());
  68.             t.setTokenDate(LocalDate.now());
  69.             t.setIpAddress(request.getRemoteAddr());
  70.             t.setUserAgent(request.getHeader("User-Agent"));
  71.             return t;
  72.         }).orElseThrow(() -> new UsernameNotFoundException("User " + steamId + " was not found in the database"));
  73.         try {
  74.             persistentTokenRepository.saveAndFlush(token);
  75.             addCookie(token, request, response);
  76.         } catch (DataAccessException e) {
  77.             log.error("Failed to save persistent token ", e);
  78.         }
  79.     }
  80.  
  81.     /**
  82.      * When logout occurs, only invalidate the current token, and not all user sessions.
  83.      * <p/>
  84.      * The standard Spring Security implementations are too basic: they invalidate all tokens for the
  85.      * current user, so when he logs out from one browser, all his other sessions are destroyed.
  86.      */
  87.     @Override
  88.     @Transactional
  89.     public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
  90.         String rememberMeCookie = extractRememberMeCookie(request);
  91.         if (rememberMeCookie != null && rememberMeCookie.length() != 0) {
  92.             try {
  93.                 String[] cookieTokens = decodeCookie(rememberMeCookie);
  94.                 PersistentToken token = getPersistentToken(cookieTokens);
  95.                 persistentTokenRepository.delete(token);
  96.             } catch (InvalidCookieException ice) {
  97.                 log.info("Invalid cookie, no persistent token could be deleted");
  98.             } catch (RememberMeAuthenticationException rmae) {
  99.                 log.debug("No persistent token found, so no token could be deleted");
  100.             }
  101.         }
  102.         super.logout(request, response, authentication);
  103.     }
  104.  
  105.     /**
  106.      * Validate the token and return it.
  107.      */
  108.     private PersistentToken getPersistentToken(String[] cookieTokens) {
  109.         if (cookieTokens.length != 2) {
  110.             throw new InvalidCookieException("Cookie token did not contain " + 2 +
  111.                 " tokens, but contained '" + Arrays.asList(cookieTokens) + "'");
  112.         }
  113.         String presentedSeries = cookieTokens[0];
  114.         String presentedToken = cookieTokens[1];
  115.         PersistentToken token = persistentTokenRepository.findOne(presentedSeries);
  116.  
  117.         if (token == null) {
  118.             // No series match, so we can't authenticate using this cookie
  119.             throw new RememberMeAuthenticationException("No persistent token found for series id: " + presentedSeries);
  120.         }
  121.  
  122.         // We have a match for this user/series combination
  123.         log.info("presentedToken={} / tokenValue={}", presentedToken, token.getTokenValue());
  124.         if (!presentedToken.equals(token.getTokenValue())) {
  125.             // Token doesn't match series value. Delete this session and throw an exception.
  126.             persistentTokenRepository.delete(token);
  127.             throw new CookieTheftException("Invalid remember-me token (Series/token) mismatch. Implies previous " +
  128.                 "cookie theft attack.");
  129.         }
  130.  
  131.         if (token.getTokenDate().plusDays(TOKEN_VALIDITY_DAYS).isBefore(LocalDate.now())) {
  132.             persistentTokenRepository.delete(token);
  133.             throw new RememberMeAuthenticationException("Remember-me login has expired");
  134.         }
  135.         return token;
  136.     }
  137.  
  138.     private String generateSeriesData() {
  139.         byte[] newSeries = new byte[DEFAULT_SERIES_LENGTH];
  140.         random.nextBytes(newSeries);
  141.         return new String(Base64.encode(newSeries));
  142.     }
  143.  
  144.     private String generateTokenData() {
  145.         byte[] newToken = new byte[DEFAULT_TOKEN_LENGTH];
  146.         random.nextBytes(newToken);
  147.         return new String(Base64.encode(newToken));
  148.     }
  149.  
  150.     private void addCookie(PersistentToken token, HttpServletRequest request, HttpServletResponse response) {
  151.         setCookie(
  152.             new String[]{token.getSeries(), token.getTokenValue()},
  153.             TOKEN_VALIDITY_SECONDS, request, response);
  154.     }
  155. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement