From 213ff93e55f39b5580e2a7ada43b770a005cc7ba Mon Sep 17 00:00:00 2001 From: Art Date: Wed, 8 Sep 2021 13:40:21 +0300 Subject: [PATCH] 59. Brute force attack cache - Guava LoadingCache Service Implementation (#6) --- support-portal-backend/pom.xml | 6 +++ .../GuavaCacheLoginAttemptService.java | 46 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/service/GuavaCacheLoginAttemptService.java diff --git a/support-portal-backend/pom.xml b/support-portal-backend/pom.xml index d1d53c3..f414d90 100644 --- a/support-portal-backend/pom.xml +++ b/support-portal-backend/pom.xml @@ -60,6 +60,12 @@ 3.12.0 + + com.google.guava + guava + 30.1.1-jre + + org.springframework.boot spring-boot-starter-test diff --git a/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/service/GuavaCacheLoginAttemptService.java b/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/service/GuavaCacheLoginAttemptService.java new file mode 100644 index 0000000..53381f2 --- /dev/null +++ b/support-portal-backend/src/main/java/net/shyshkin/study/fullstack/supportportal/backend/service/GuavaCacheLoginAttemptService.java @@ -0,0 +1,46 @@ +package net.shyshkin.study.fullstack.supportportal.backend.service; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +@Service +@Primary +public class GuavaCacheLoginAttemptService implements LoginAttemptService { + + private LoadingCache loginAttemptsCache = CacheBuilder.newBuilder() + .expireAfterWrite(15, TimeUnit.MINUTES) + .maximumSize(100) + .build(new CacheLoader<>() { + @Override + public Integer load(String key) throws Exception { + return 0; + } + }); + + @Override + public void loginFailed(String username) { + int attempts = getAttempts(username); + loginAttemptsCache.put(username, attempts + ATTEMPT_INCREMENT); + } + + @Override + public void loginSucceeded(String username) { + loginAttemptsCache.invalidate(username); + } + + @Override + public boolean hasExceededMaxAttempts(String username) { + return getAttempts(username) >= MAX_ATTEMPTS; + } + + private int getAttempts(String username) { + Integer attempts = loginAttemptsCache.getIfPresent(username); + return Objects.requireNonNullElse(attempts, 0); + } +}