All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.albertus82.net.httpserver.HttpServerAuthenticator Maven / Gradle / Ivy

Go to download

Java SWT/JFace Utility Library including a Preferences Framework, Lightweight HTTP Server and macOS support.

There is a newer version: 20.1.0
Show newest version
package io.github.albertus82.net.httpserver;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.bind.DatatypeConverter;

import com.sun.net.httpserver.BasicAuthenticator;
import com.sun.net.httpserver.HttpExchange;

import io.github.albertus82.jface.JFaceMessages;
import io.github.albertus82.net.httpserver.config.IAuthenticatorConfig;
import io.github.albertus82.util.StringUtils;
import io.github.albertus82.util.logging.LoggerFactory;

@SuppressWarnings("restriction")
public class HttpServerAuthenticator extends BasicAuthenticator {

	private static final Logger log = LoggerFactory.getLogger(HttpServerAuthenticator.class);

	private final IAuthenticatorConfig configuration;
	private Charset charset = StandardCharsets.UTF_8;

	private final ThreadLocal exchanges = new ThreadLocal<>();

	public HttpServerAuthenticator(final IAuthenticatorConfig configuration) {
		super(configuration.getRealm());
		this.configuration = configuration;
	}

	@Override
	public Result authenticate(final HttpExchange exchange) {
		try {
			exchanges.set(exchange); // used in checkCredentials(...)
			return super.authenticate(exchange);
		}
		finally {
			exchanges.remove();
		}
	}

	@Override
	public boolean checkCredentials(final String specifiedUsername, final String specifiedPassword) {
		try {
			if (specifiedUsername == null || specifiedUsername.isEmpty() || specifiedPassword == null || specifiedPassword.isEmpty()) {
				return fail();
			}

			final char[] expectedPassword = getConfiguration().getPassword(specifiedUsername);
			if (expectedPassword != null && expectedPassword.length > 0 && checkPassword(specifiedPassword, expectedPassword)) {
				return true;
			}
			else {
				final HttpExchange exchange = exchanges.get();
				log.log(Level.parse(getConfiguration().getFailureLoggingLevel()), JFaceMessages.get("err.httpserver.authentication"), new Object[] { specifiedUsername, specifiedPassword, exchange != null ? exchange.getRemoteAddress() : null });
				return fail();
			}
		}
		catch (final Exception e) {
			log.log(Level.SEVERE, "An error occurred while checking credentials:", e);
			return fail();
		}
	}

	protected boolean checkPassword(final String provided, final char[] expected) {
		final char[] computed;
		if (StringUtils.isNotBlank(configuration.getPasswordHashAlgorithm())) {
			computed = DatatypeConverter.printHexBinary(newMessageDigest(configuration.getPasswordHashAlgorithm().trim()).digest(provided.getBytes(charset))).toLowerCase(Locale.ROOT).toCharArray();
		}
		else {
			computed = provided.toCharArray();
		}

		boolean equal = true;
		if (computed.length != expected.length) {
			equal = false;
		}
		for (int i = 0; i < 0x400; i++) {
			if (computed[i % computed.length] != expected[i % expected.length]) {
				equal = false;
			}
		}
		return equal;
	}

	protected boolean fail() {
		try {
			TimeUnit.MILLISECONDS.sleep(configuration.getFailDelayMillis());
		}
		catch (final InterruptedException e) {
			log.log(Level.FINE, "Sleep interrupted:", e);
			Thread.currentThread().interrupt();
		}
		return false;
	}

	public Charset getCharset() {
		return charset;
	}

	public void setCharset(final Charset charset) {
		this.charset = charset;
	}

	protected IAuthenticatorConfig getConfiguration() {
		return configuration;
	}

	private static MessageDigest newMessageDigest(final String algorithm) {
		try {
			return MessageDigest.getInstance(algorithm);
		}
		catch (final NoSuchAlgorithmException e) {
			throw new IllegalArgumentException(algorithm, e);
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy