LoginSystem/src/main/java/fr/xephi/authme/data/captcha/LoginCaptchaManager.java
ljacqu 84b376d2a5 #930 Change captcha storage to change code internally upon failure
- Within CaptchaStorage#checkCode, a player's captcha code is overridden with a new one on failure or cleared on success
- Fixes inconsistencies in the retrieval / regeneration of codes
2018-01-06 02:31:26 +01:00

95 lines
3.1 KiB
Java

package fr.xephi.authme.data.captcha;
import fr.xephi.authme.initialization.HasCleanup;
import fr.xephi.authme.initialization.SettingsDependent;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.expiring.TimedCounter;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import java.util.concurrent.TimeUnit;
/**
* Manager for the handling of captchas after too many failed login attempts.
*/
public class LoginCaptchaManager implements CaptchaManager, SettingsDependent, HasCleanup {
private final TimedCounter<String> playerCounts;
private final CaptchaCodeStorage captchaCodeStorage;
private boolean isEnabled;
private int threshold;
@Inject
LoginCaptchaManager(Settings settings) {
// Note: Proper values are set in reload()
this.captchaCodeStorage = new CaptchaCodeStorage(30, 4);
this.playerCounts = new TimedCounter<>(9, TimeUnit.MINUTES);
reload(settings);
}
/**
* Increases the failure count for the given player.
*
* @param name the player's name
*/
public void increaseLoginFailureCount(String name) {
if (isEnabled) {
String playerLower = name.toLowerCase();
playerCounts.increment(playerLower);
}
}
@Override
public boolean isCaptchaRequired(String playerName) {
return isEnabled && playerCounts.get(playerName.toLowerCase()) >= threshold;
}
@Override
public String getCaptchaCodeOrGenerateNew(String name) {
return captchaCodeStorage.getCodeOrGenerateNew(name);
}
@Override
public boolean checkCode(Player player, String code) {
String nameLower = player.getName().toLowerCase();
boolean isCodeCorrect = captchaCodeStorage.checkCode(nameLower, code);
if (isCodeCorrect) {
playerCounts.remove(nameLower);
}
return isCodeCorrect;
}
/**
* Resets the login count of the given player to 0.
*
* @param name the player's name
*/
public void resetLoginFailureCount(String name) {
if (isEnabled) {
playerCounts.remove(name.toLowerCase());
}
}
@Override
public void reload(Settings settings) {
int expirationInMinutes = settings.getProperty(SecuritySettings.CAPTCHA_COUNT_MINUTES_BEFORE_RESET);
captchaCodeStorage.setExpirationInMinutes(expirationInMinutes);
int captchaLength = settings.getProperty(SecuritySettings.CAPTCHA_LENGTH);
captchaCodeStorage.setCaptchaLength(captchaLength);
int countTimeout = settings.getProperty(SecuritySettings.CAPTCHA_COUNT_MINUTES_BEFORE_RESET);
playerCounts.setExpiration(countTimeout, TimeUnit.MINUTES);
isEnabled = settings.getProperty(SecuritySettings.ENABLE_LOGIN_FAILURE_CAPTCHA);
threshold = settings.getProperty(SecuritySettings.MAX_LOGIN_TRIES_BEFORE_CAPTCHA);
}
@Override
public void performCleanup() {
playerCounts.removeExpiredEntries();
captchaCodeStorage.removeExpiredEntries();
}
}