11package org .cloudfoundry .identity .uaa .util ;
22
3- import com .google .common .cache .Cache ;
4- import com .google .common .cache .CacheBuilder ;
3+ import com .github .benmanes .caffeine .cache .Cache ;
4+ import com .github .benmanes .caffeine .cache .Caffeine ;
5+ import com .google .common .annotations .VisibleForTesting ;
6+ import org .cloudfoundry .identity .uaa .oauth .common .util .RandomValueStringGenerator ;
57import org .springframework .security .core .AuthenticationException ;
68import org .springframework .security .crypto .codec .Hex ;
79import org .springframework .security .crypto .codec .Utf8 ;
810import org .springframework .security .crypto .keygen .KeyGenerators ;
911import org .springframework .security .crypto .password .PasswordEncoder ;
10- import org .cloudfoundry .identity .uaa .oauth .common .util .RandomValueStringGenerator ;
1112
1213import java .security .MessageDigest ;
1314import java .security .NoSuchAlgorithmException ;
1819import java .util .List ;
1920import java .util .Set ;
2021import java .util .concurrent .ConcurrentMap ;
21- import java .util .concurrent .TimeUnit ;
2222
2323import static org .springframework .security .crypto .util .EncodingUtils .concatenate ;
2424
2828 */
2929public class CachingPasswordEncoder implements PasswordEncoder {
3030
31+ private static final int ITERATIONS = 25 ;
32+ private static final int MAX_KEYS = 1000 ;
33+ private static final int MAX_ENCODED_PASSWORDS = 5 ;
34+
35+ @ VisibleForTesting
36+ static Duration DEFAULT_CACHE_TTL = Duration .ofMinutes (5L );
37+
3138 private final MessageDigest messageDigest ;
3239 private final byte [] secret ;
3340 private final byte [] salt ;
3441
35- private static final int ITERATIONS = 25 ;
36- private static final int MAX_KEYS = 1000 ;
37- private static final int MAX_ENCODED_PASSWORDS = 5 ;
38- private final Duration CACHE_TTL = Duration .ofMinutes (5L );
39- private volatile Cache <CharSequence , Set <String >> cache ;
42+ private final Cache <CharSequence , Set <String >> cache ;
4043
4144 private final PasswordEncoder passwordEncoder ;
4245
4346 CachingPasswordEncoder (final PasswordEncoder passwordEncoder ) throws NoSuchAlgorithmException {
4447 this .passwordEncoder = passwordEncoder ;
45- this .messageDigest = MessageDigest .getInstance ("SHA-256" );
46- this .secret = Utf8 .encode (new RandomValueStringGenerator ().generate ());
47- this .salt = KeyGenerators .secureRandom ().generateKey ();
48- buildCache ();
48+ messageDigest = MessageDigest .getInstance ("SHA-256" );
49+ secret = Utf8 .encode (new RandomValueStringGenerator ().generate ());
50+ salt = KeyGenerators .secureRandom ().generateKey ();
51+ cache = Caffeine .newBuilder ()
52+ .expireAfterWrite (DEFAULT_CACHE_TTL )
53+ .maximumSize (MAX_KEYS )
54+ .build ();
4955 }
5056
5157 @ Override
@@ -65,7 +71,7 @@ public boolean matches(CharSequence rawPassword, String encodedPassword) throws
6571 Set <String > getOrCreateHashList (String cacheKey ) {
6672 Set <String > result = cache .getIfPresent (cacheKey );
6773 if (result == null ) {
68- if (cache .size () >= MAX_KEYS ) {
74+ if (cache .estimatedSize () >= MAX_KEYS ) {
6975 cache .invalidateAll ();
7076 }
7177 cache .put (cacheKey , Collections .synchronizedSet (new LinkedHashSet <>()));
@@ -86,8 +92,8 @@ private boolean internalMatches(String cacheKey, CharSequence rawPassword, Strin
8692 result = true ;
8793 cacheValue = getOrCreateHashList (cacheKey );
8894 if (cacheValue != null ) {
89- //this list should never grow very long.
90- //Only if you store multiple versions of the same password more than once
95+ // This list should never grow very long.
96+ // Only if you store multiple versions of the same password more than once
9197 if (cacheValue .size () >= MAX_ENCODED_PASSWORDS ) {
9298 cacheValue .clear ();
9399 }
@@ -140,16 +146,10 @@ int getMaxEncodedPasswords() {
140146 }
141147
142148 long getNumberOfKeys () {
143- return cache .size ();
149+ return cache .estimatedSize ();
144150 }
145151
146152 ConcurrentMap <CharSequence , Set <String >> asMap () {
147153 return cache .asMap ();
148154 }
149-
150- void buildCache () {
151- cache = CacheBuilder .newBuilder ()
152- .expireAfterWrite (CACHE_TTL .getSeconds (), TimeUnit .SECONDS )
153- .build ();
154- }
155155}
0 commit comments