我正在尝试实现Caffeine缓存以避免暴力登录尝试。这样我就有了一个缓存,其键为IP地址,值=登录尝试次数。
我有一个构建Caffeine缓存的服务,以及一些处理登录失败和成功事件的方法。如果用户提供了错误的凭据,则将调用loginFailed(String key)
方法。但是,getIfPresent(key)
即使在put方法起作用后也始终返回null。
顺便说一下,IP地址来自 AuthenticationFailureListener 组件。
我曾经尝试过使用Google的Guava Cache,但是它已被弃用,并替换为咖啡因。
LoginAttemptService
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class LoginAttemptService {
@Value("${captcha.maxAttempt}")
private int MAX_ATTEMPT;
@Value("${captcha.attemptExpirationHour}")
private int ATTEMPT_EXPIRE_DURATION;
private Cache<String, Integer> attemptsCache;
public LoginAttemptService() {
super();
attemptsCache = Caffeine.newBuilder().
expireAfterWrite(ATTEMPT_EXPIRE_DURATION, TimeUnit.HOURS).build();
}
public void loginSucceeded(String key) {
attemptsCache.invalidate(key);
}
public void loginFailed(String key) {
Integer attempts = attemptsCache.getIfPresent(key);
if (attempts != null) {
attempts++;
attemptsCache.put(key, attempts);
} else {
attemptsCache.put(key, 1);
}
}
public boolean isBlocked(String key) {
Integer numberOfAttemps = attemptsCache.getIfPresent(key);
if (numberOfAttemps != null) {
return numberOfAttemps >= MAX_ATTEMPT;
} else {
return false;
}
}
}
上面的代码中,我期望调用isBlocked(String key)
方法时,它应该返回给定密钥的尝试次数,即IP地址。
编辑:我实际上已经找到了问题所在。如果我不将expireAfterWrite
放到Caffeine Builder中,它的效果会很好。但是我不知道为什么它不起作用。