Empty encoded password when using @Cacheable in UserDetailsService

元气小坏坏 提交于 2020-12-12 01:31:17

问题


Faced a problem with caching during authorization, I can't figure it out. So that during authorization every time a request is not made to the database, I want to cache the method. At the first request with an empty cache, everything is fine and until the cache is deleted after a time. But while the cache is there, I get 401, because o.s.s.c.bcrypt.BCryptPasswordEncoder: Empty encoded password, the password is empty every time. How to be in such a situation?

   @Override
    @Transactional
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        log.debug("Load user {}", username);
        return userService.findUserDetailsByName(username).orElseThrow(() -> new UsernameNotFoundException(username));
    }
 
    @Cacheable(cacheNames = Caches.USER_DETAILS_CACHE)
    public Optional<UserDetails> findUserDetailsByName(String username) {
            Optional<UserDetails> userDetailsOpt =
                    userRepository.findOne(QUser.user.userName.eq(username)).map(UserService::createFrom);
            return userDetailsOpt.map(u -> withUserDetails(u).build());
    }
 
@Configuration(proxyBeanMethods = false)
@EnableCaching
@RequiredArgsConstructor
public class CacheConfiguration {
    @Bean
    public CacheManager cacheManager(Ticker ticker, @Value("${app.cache.user.ttl}") Duration userTtl) {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        List<CaffeineCache> caches = new ArrayList<>();
        caches.add(buildCache(Caches.USER_DETAILS_CACHE, ticker, userTtl, 1));
        cacheManager.setCaches(caches);
        return cacheManager;
    }
 
    @Bean
    public Ticker ticker() {
        return Ticker.systemTicker();
    }
 
    private static CaffeineCache buildCache(String name, Ticker ticker, Duration ttl, int size) {
        return new CaffeineCache(name, Caffeine.newBuilder()
                .expireAfterWrite(ttl)
                .ticker(ticker)
                .maximumSize(size)
                .build());
    }
}


回答1:


Assuming you are using the default Spring Security User as the UserDetails implementation. This implements CredentialsContainer which will have its password cleared after use for security reasons.

The caching is done for the object instance instead of raw data and thus it will be cleared in the cache as well.

If you are using JPA you better use the 2nd level caching integration of your JPA provider instead of external caching.




回答2:


I solved the problem this way

    private final Cache userDetailsCache;
    public UserService(CacheManager cacheManager) {
        this.userDetailsCache = cacheManager.getCache(Caches.USER_DETAILS_CACHE);
    }
      public Optional<UserDetails> findUserDetailsByName(String username) {
        ValueWrapper value = userDetailsCache.get(username);
        if (value == null) {
            Optional<UserDetails> userDetailsOpt =
                    userRepository.findOne(QUser.user.userName.eq(username)).map(UserService::createFrom);
            userDetailsOpt.ifPresent(u -> userDetailsCache.put(username, u));
            return userDetailsOpt.map(u -> withUserDetails(u).build());
        } else {
            return Optional.ofNullable((UserDetails) value.get()).map(u -> withUserDetails(u).build());
        }
    }

      


来源:https://stackoverflow.com/questions/65177102/empty-encoded-password-when-using-cacheable-in-userdetailsservice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!