org.eclipse.jetty.security.PropertyUserStore Maven / Gradle / Ivy
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.security;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.eclipse.jetty.io.IOResources;
import org.eclipse.jetty.util.Scanner;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.Resources;
import org.eclipse.jetty.util.security.Credential;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class monitors a property file of the format mentioned below
* and notifies registered listeners of the changes to the the given file.
*
*
* username: password [,rolename ...]
*
*
* Passwords may be clear text, obfuscated or checksummed.
* The class {@link org.eclipse.jetty.util.security.Password} should be used
* to generate obfuscated passwords or password checksums.
*
* If DIGEST Authentication is used, the password must be in a recoverable
* format, either plain text or obfuscated.
*/
public class PropertyUserStore extends UserStore implements Scanner.DiscreteListener
{
private static final Logger LOG = LoggerFactory.getLogger(PropertyUserStore.class);
protected Resource _configResource;
protected Scanner _scanner;
protected int _reloadInterval = 0;
protected boolean _firstLoad = true; // true if first load, false from that point on
protected List _listeners;
/**
* Get the config (as a string)
*
* @return the config path as a string
*/
public Resource getConfig()
{
return _configResource;
}
/**
* Set the Config Path from a String reference to a file
*
* @param config the config file
* TODO: reintroduce setConfig(String) and internal ResourceFactory usage
*/
public void setConfig(Resource config)
{
_configResource = config;
}
/**
* @return the resource associated with the configured properties file, creating it if necessary
* @deprecated
*/
@Deprecated(forRemoval = true)
public Resource getConfigResource()
{
return getConfig();
}
/**
* Is hot reload enabled on this user store
*
* @return true if hot reload was enabled before startup
* @deprecated use {@link #getReloadInterval()}
*/
@Deprecated
public boolean isHotReload()
{
return getReloadInterval() > 0;
}
/**
* Enable Hot Reload of the Property File
*
* @param enable true to enable to a 1 second scan, false to disable
* @deprecated use {@link #setReloadInterval(int)}
*/
@Deprecated
public void setHotReload(boolean enable)
{
setReloadInterval(enable ? 1 : 0);
}
/**
* Enable Hot Reload of the Property File
*
* @param scanSeconds the period in seconds to scan for property file changes, or 0 for no scanning
*/
public void setReloadInterval(int scanSeconds)
{
if (isRunning())
{
throw new IllegalStateException("Cannot set scan period while user store is running");
}
this._reloadInterval = scanSeconds;
}
/**
* Get the period in seconds to scan for property file changes, or 0 for no scanning.
* @return the period in seconds to scan for property file changes, or 0 for no scanning
*/
public int getReloadInterval()
{
return _reloadInterval;
}
@Override
public String toString()
{
return String.format("%s[cfg=%s]", super.toString(), _configResource);
}
/**
* Load the user data from the property file.
* @throws IOException If the users cannot be loaded
*/
protected void loadUsers() throws IOException
{
Resource config = getConfig();
if (config == null)
throw new IllegalStateException("No config path set");
if (LOG.isDebugEnabled())
LOG.debug("Loading {} from {}", this, config);
if (Resources.missing(config))
throw new IllegalStateException("Config does not exist: " + config);
Properties properties = new Properties();
try (InputStream inputStream = IOResources.asInputStream(config))
{
properties.load(inputStream);
}
Set known = new HashSet<>();
for (Map.Entry
© 2015 - 2025 Weber Informatics LLC | Privacy Policy