package launchserver.auth.provider; import java.io.BufferedReader; import java.io.IOException; import java.nio.file.Path; import java.nio.file.attribute.FileTime; import java.util.HashMap; import java.util.Map; import launcher.helper.IOHelper; import launcher.helper.LogHelper; import launcher.serialize.config.entry.BlockConfigEntry; import launcher.serialize.config.entry.StringConfigEntry; import launchserver.helper.LineReader; public final class FileAuthProvider extends DigestAuthProvider { private final Path file; // Cache private final Map<String, String> cache = new HashMap<>(8192); private final Object cacheLock = new Object(); private FileTime cacheLastModified; public FileAuthProvider(BlockConfigEntry block) { super(block); file = IOHelper.toPath(block.getEntryValue("file", StringConfigEntry.class)); } @Override public String auth(String login, String password) throws IOException { String validDigest; synchronized (cacheLock) { updateCache(); validDigest = cache.get(login); } verifyDigest(validDigest, password); return login; } @Override public void flush() { // Do nothing } private void updateCache() throws IOException { FileTime lastModified = IOHelper.readAttributes(file).lastModifiedTime(); if (lastModified.equals(cacheLastModified)) { return; // Not modified, so cache is up-to-date } // Read file cache.clear(); LogHelper.info("Recaching users file: '%s'", file); try (BufferedReader reader = new LineReader(IOHelper.newReader(file))) { for (String line = reader.readLine(); line != null; line = reader.readLine()) { // Get and verify split index int splitIndex = line.indexOf(':'); if (splitIndex < 0) { throw new IOException(String.format("Illegal line in users file: '%s'", line)); } // Split and verify username and password String username = line.substring(0, splitIndex).trim(); String password = line.substring(splitIndex + 1).trim(); if (username.isEmpty() || password.isEmpty()) { throw new IOException(String.format("Empty username or password in users file: '%s'", line)); } // Try put to cache if (cache.put(username, password) != null) { throw new IOException(String.format("Duplicate username in users file: '%s'", username)); } } } // Update last modified time cacheLastModified = lastModified; } }